@@ -43,6 +43,7 @@ pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
43
43
borrows : IndexVec < BorrowIndex , BorrowData < ' tcx > > ,
44
44
location_map : FxHashMap < Location , BorrowIndex > ,
45
45
region_map : FxHashMap < Region < ' tcx > , FxHashSet < BorrowIndex > > ,
46
+ local_map : FxHashMap < mir:: Local , FxHashSet < BorrowIndex > > ,
46
47
region_span_map : FxHashMap < RegionKind , Span > ,
47
48
nonlexical_regioncx : Option < RegionInferenceContext < ' tcx > > ,
48
49
}
@@ -89,6 +90,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
89
90
idx_vec : IndexVec :: new ( ) ,
90
91
location_map : FxHashMap ( ) ,
91
92
region_map : FxHashMap ( ) ,
93
+ local_map : FxHashMap ( ) ,
92
94
region_span_map : FxHashMap ( )
93
95
} ;
94
96
visitor. visit_mir ( mir) ;
@@ -99,6 +101,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
99
101
root_scope,
100
102
location_map : visitor. location_map ,
101
103
region_map : visitor. region_map ,
104
+ local_map : visitor. local_map ,
102
105
region_span_map : visitor. region_span_map ,
103
106
nonlexical_regioncx } ;
104
107
@@ -108,13 +111,22 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
108
111
idx_vec : IndexVec < BorrowIndex , BorrowData < ' tcx > > ,
109
112
location_map : FxHashMap < Location , BorrowIndex > ,
110
113
region_map : FxHashMap < Region < ' tcx > , FxHashSet < BorrowIndex > > ,
114
+ local_map : FxHashMap < mir:: Local , FxHashSet < BorrowIndex > > ,
111
115
region_span_map : FxHashMap < RegionKind , Span > ,
112
116
}
113
117
114
118
impl < ' a , ' gcx , ' tcx > Visitor < ' tcx > for GatherBorrows < ' a , ' gcx , ' tcx > {
115
119
fn visit_rvalue ( & mut self ,
116
120
rvalue : & mir:: Rvalue < ' tcx > ,
117
121
location : mir:: Location ) {
122
+ fn root_local ( mut p : & mir:: Place < ' _ > ) -> Option < mir:: Local > {
123
+ loop { match p {
124
+ mir:: Place :: Projection ( pi) => p = & pi. base ,
125
+ mir:: Place :: Static ( _) => return None ,
126
+ mir:: Place :: Local ( l) => return Some ( * l)
127
+ } }
128
+ }
129
+
118
130
if let mir:: Rvalue :: Ref ( region, kind, ref place) = * rvalue {
119
131
if is_unsafe_place ( self . tcx , self . mir , place) { return ; }
120
132
@@ -123,8 +135,14 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
123
135
} ;
124
136
let idx = self . idx_vec . push ( borrow) ;
125
137
self . location_map . insert ( location, idx) ;
138
+
126
139
let borrows = self . region_map . entry ( region) . or_insert ( FxHashSet ( ) ) ;
127
140
borrows. insert ( idx) ;
141
+
142
+ if let Some ( local) = root_local ( place) {
143
+ let borrows = self . local_map . entry ( local) . or_insert ( FxHashSet ( ) ) ;
144
+ borrows. insert ( idx) ;
145
+ }
128
146
}
129
147
}
130
148
@@ -213,7 +231,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
213
231
mir:: StatementKind :: EndRegion ( region_scope) => {
214
232
if let Some ( borrow_indexes) = self . region_map . get ( & ReScope ( region_scope) ) {
215
233
assert ! ( self . nonlexical_regioncx. is_none( ) ) ;
216
- for idx in borrow_indexes { sets. kill ( & idx ) ; }
234
+ sets. kill_all ( borrow_indexes ) ;
217
235
} else {
218
236
// (if there is no entry, then there are no borrows to be tracked)
219
237
}
@@ -238,10 +256,19 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
238
256
}
239
257
}
240
258
259
+ mir:: StatementKind :: StorageDead ( local) => {
260
+ // Make sure there are no remaining borrows for locals that
261
+ // are gone out of scope.
262
+ //
263
+ // FIXME: expand this to variables that are assigned over.
264
+ if let Some ( borrow_indexes) = self . local_map . get ( & local) {
265
+ sets. kill_all ( borrow_indexes) ;
266
+ }
267
+ }
268
+
241
269
mir:: StatementKind :: InlineAsm { .. } |
242
270
mir:: StatementKind :: SetDiscriminant { .. } |
243
271
mir:: StatementKind :: StorageLive ( ..) |
244
- mir:: StatementKind :: StorageDead ( ..) |
245
272
mir:: StatementKind :: Validate ( ..) |
246
273
mir:: StatementKind :: Nop => { }
247
274
0 commit comments