10
10
11
11
use borrow_check:: place_ext:: PlaceExt ;
12
12
use dataflow:: indexes:: BorrowIndex ;
13
+ use dataflow:: move_paths:: MoveData ;
13
14
use rustc:: mir:: traversal;
14
15
use rustc:: mir:: visit:: { PlaceContext , Visitor } ;
15
- use rustc:: mir:: { self , Location , Mir , Place } ;
16
+ use rustc:: mir:: { self , Location , Mir , Place , Local } ;
16
17
use rustc:: ty:: { Region , TyCtxt } ;
17
18
use rustc:: util:: nodemap:: { FxHashMap , FxHashSet } ;
18
19
use rustc_data_structures:: indexed_vec:: IndexVec ;
20
+ use rustc_data_structures:: bitvec:: BitArray ;
19
21
use std:: fmt;
20
22
use std:: hash:: Hash ;
21
23
use std:: ops:: Index ;
@@ -43,6 +45,8 @@ crate struct BorrowSet<'tcx> {
43
45
44
46
/// Map from local to all the borrows on that local
45
47
crate local_map : FxHashMap < mir:: Local , FxHashSet < BorrowIndex > > ,
48
+
49
+ crate locals_state_at_exit : LocalsStateAtExit ,
46
50
}
47
51
48
52
impl < ' tcx > Index < BorrowIndex > for BorrowSet < ' tcx > {
@@ -96,8 +100,52 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
96
100
}
97
101
}
98
102
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
+
99
141
impl < ' 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
+
101
149
let mut visitor = GatherBorrows {
102
150
tcx,
103
151
mir,
@@ -107,6 +155,8 @@ impl<'tcx> BorrowSet<'tcx> {
107
155
region_map : FxHashMap ( ) ,
108
156
local_map : FxHashMap ( ) ,
109
157
pending_activations : FxHashMap ( ) ,
158
+ locals_state_at_exit :
159
+ LocalsStateAtExit :: build ( locals_are_invalidated_at_exit, mir, move_data) ,
110
160
} ;
111
161
112
162
for ( block, block_data) in traversal:: preorder ( mir) {
@@ -119,6 +169,7 @@ impl<'tcx> BorrowSet<'tcx> {
119
169
activation_map : visitor. activation_map ,
120
170
region_map : visitor. region_map ,
121
171
local_map : visitor. local_map ,
172
+ locals_state_at_exit : visitor. locals_state_at_exit ,
122
173
}
123
174
}
124
175
@@ -148,6 +199,8 @@ struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
148
199
/// the borrow. When we find a later use of this activation, we
149
200
/// remove from the map (and add to the "tombstone" set below).
150
201
pending_activations : FxHashMap < mir:: Local , BorrowIndex > ,
202
+
203
+ locals_state_at_exit : LocalsStateAtExit ,
151
204
}
152
205
153
206
impl < ' 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> {
159
212
location : mir:: Location ,
160
213
) {
161
214
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 ) {
163
217
return ;
164
218
}
165
219
0 commit comments