Skip to content

Commit 965eef9

Browse files
invalidates: properly handle terminators
1 parent a82c097 commit 965eef9

File tree

1 file changed

+41
-26
lines changed

1 file changed

+41
-26
lines changed

src/librustc_mir/borrow_check/nll/invalidation.rs

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)