@@ -234,38 +234,29 @@ impl<'cg, 'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cg, 'cx, 'tc
234234 }
235235 TerminatorKind :: Yield {
236236 ref value,
237- resume : _ ,
237+ resume,
238238 drop : _,
239239 } => {
240240 self . consume_operand ( ContextKind :: Yield . new ( location) , value) ;
241241
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+ }
253250 }
254251 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+ }
269260 }
270261 TerminatorKind :: Goto { target : _ }
271262 | TerminatorKind :: Abort
@@ -953,3 +944,27 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cg, 'cx, 'tcx, 'gcx> {
953944 }
954945 }
955946}
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