@@ -234,38 +234,29 @@ impl<'cg, 'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cg, 'cx, 'tc
234
234
}
235
235
TerminatorKind :: Yield {
236
236
ref value,
237
- resume : _ ,
237
+ resume,
238
238
drop : _,
239
239
} => {
240
240
self . consume_operand ( ContextKind :: Yield . new ( location) , value) ;
241
241
242
- // ** FIXME(bob_twinkles) figure out what the equivalent of this is
243
- // if self.movable_generator {
244
- // // Look for any active borrows to locals
245
- // let borrow_set = self.borrow_set.clone();
246
- // flow_state.with_outgoing_borrows(|borrows| {
247
- // for i in borrows {
248
- // let borrow = &borrow_set[i];
249
- // self.check_for_local_borrow(borrow, span);
250
- // }
251
- // });
252
- // }
242
+ // Invalidate all borrows of local places
243
+ let borrow_set = self . borrow_set . clone ( ) ;
244
+ let resume = self . location_table . start_index ( resume. start_location ( ) ) ;
245
+ for i in borrow_set. borrows . indices ( ) {
246
+ if borrow_of_local_data ( & borrow_set. borrows [ i] . borrowed_place ) {
247
+ self . all_facts . invalidates . push ( ( resume, i) ) ;
248
+ }
249
+ }
253
250
}
254
251
TerminatorKind :: Resume | TerminatorKind :: Return | TerminatorKind :: GeneratorDrop => {
255
- // ** FIXME(bob_twinkles) figure out what the equivalent of this is
256
- // // Returning from the function implicitly kills storage for all locals and
257
- // // statics.
258
- // // Often, the storage will already have been killed by an explicit
259
- // // StorageDead, but we don't always emit those (notably on unwind paths),
260
- // // so this "extra check" serves as a kind of backup.
261
- // let borrow_set = self.borrow_set.clone();
262
- // flow_state.with_outgoing_borrows(|borrows| {
263
- // for i in borrows {
264
- // let borrow = &borrow_set[i];
265
- // let context = ContextKind::StorageDead.new(loc);
266
- // self.check_for_invalidation_at_exit(context, borrow, span);
267
- // }
268
- // });
252
+ // Invalidate all borrows of local places
253
+ let borrow_set = self . borrow_set . clone ( ) ;
254
+ let start = self . location_table . start_index ( location) ;
255
+ for i in borrow_set. borrows . indices ( ) {
256
+ if borrow_of_local_data ( & borrow_set. borrows [ i] . borrowed_place ) {
257
+ self . all_facts . invalidates . push ( ( start, i) ) ;
258
+ }
259
+ }
269
260
}
270
261
TerminatorKind :: Goto { target : _ }
271
262
| TerminatorKind :: Abort
@@ -953,3 +944,27 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cg, 'cx, 'tcx, 'gcx> {
953
944
}
954
945
}
955
946
}
947
+
948
+
949
+ /// Determines if a given borrow is borrowing local data
950
+ /// This is called for all Yield statements on movable generators
951
+ fn borrow_of_local_data < ' tcx > ( place : & Place < ' tcx > ) -> bool {
952
+ match place {
953
+ Place :: Static ( ..) => false ,
954
+ Place :: Local ( ..) => true ,
955
+ Place :: Projection ( box proj) => {
956
+ match proj. elem {
957
+ // Reborrow of already borrowed data is ignored
958
+ // Any errors will be caught on the initial borrow
959
+ ProjectionElem :: Deref => false ,
960
+
961
+ // For interior references and downcasts, find out if the base is local
962
+ ProjectionElem :: Field ( ..)
963
+ | ProjectionElem :: Index ( ..)
964
+ | ProjectionElem :: ConstantIndex { .. }
965
+ | ProjectionElem :: Subslice { .. }
966
+ | ProjectionElem :: Downcast ( ..) => borrow_of_local_data ( & proj. base ) ,
967
+ }
968
+ }
969
+ }
970
+ }
0 commit comments