about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbobtwinkles <srkoser+github@gmail.com>2018-05-17 00:49:06 -0700
committerbobtwinkles <srkoser+github@gmail.com>2018-05-17 00:49:06 -0700
commit965eef92c45297e2c54ca429e1c1bf7e324f3351 (patch)
treee4a339876667cc4cf5eed28ae2969745f5cc3ffc
parenta82c0972965c70c8f061c20a68f2e498bd12367f (diff)
invalidates: properly handle terminators
-rw-r--r--src/librustc_mir/borrow_check/nll/invalidation.rs67
1 files changed, 41 insertions, 26 deletions
diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs
index 35adbc99e29..f6704648cb5 100644
--- a/src/librustc_mir/borrow_check/nll/invalidation.rs
+++ b/src/librustc_mir/borrow_check/nll/invalidation.rs
@@ -234,38 +234,29 @@ impl<'cg, 'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cg, 'cx, 'tc
             }
             TerminatorKind::Yield {
                 ref value,
-                resume: _,
+                resume,
                 drop: _,
             } => {
                 self.consume_operand(ContextKind::Yield.new(location), value);
 
-                // ** FIXME(bob_twinkles) figure out what the equivalent of this is
-                // if self.movable_generator {
-                //     // Look for any active borrows to locals
-                //     let borrow_set = self.borrow_set.clone();
-                //     flow_state.with_outgoing_borrows(|borrows| {
-                //         for i in borrows {
-                //             let borrow = &borrow_set[i];
-                //             self.check_for_local_borrow(borrow, span);
-                //         }
-                //     });
-                // }
+                // Invalidate all borrows of local places
+                let borrow_set = self.borrow_set.clone();
+                let resume = self.location_table.start_index(resume.start_location());
+                for i in borrow_set.borrows.indices() {
+                    if borrow_of_local_data(&borrow_set.borrows[i].borrowed_place) {
+                        self.all_facts.invalidates.push((resume, i));
+                    }
+                }
             }
             TerminatorKind::Resume | TerminatorKind::Return | TerminatorKind::GeneratorDrop => {
-                // ** FIXME(bob_twinkles) figure out what the equivalent of this is
-                // // Returning from the function implicitly kills storage for all locals and
-                // // statics.
-                // // Often, the storage will already have been killed by an explicit
-                // // StorageDead, but we don't always emit those (notably on unwind paths),
-                // // so this "extra check" serves as a kind of backup.
-                // let borrow_set = self.borrow_set.clone();
-                // flow_state.with_outgoing_borrows(|borrows| {
-                //     for i in borrows {
-                //         let borrow = &borrow_set[i];
-                //         let context = ContextKind::StorageDead.new(loc);
-                //         self.check_for_invalidation_at_exit(context, borrow, span);
-                //     }
-                // });
+                // Invalidate all borrows of local places
+                let borrow_set = self.borrow_set.clone();
+                let start = self.location_table.start_index(location);
+                for i in borrow_set.borrows.indices() {
+                    if borrow_of_local_data(&borrow_set.borrows[i].borrowed_place) {
+                        self.all_facts.invalidates.push((start, i));
+                    }
+                }
             }
             TerminatorKind::Goto { target: _ }
             | TerminatorKind::Abort
@@ -953,3 +944,27 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cg, 'cx, 'tcx, 'gcx> {
         }
     }
 }
+
+
+/// Determines if a given borrow is borrowing local data
+/// This is called for all Yield statements on movable generators
+fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool {
+    match place {
+        Place::Static(..) => false,
+        Place::Local(..) => true,
+        Place::Projection(box proj) => {
+            match proj.elem {
+                // Reborrow of already borrowed data is ignored
+                // Any errors will be caught on the initial borrow
+                ProjectionElem::Deref => false,
+
+                // For interior references and downcasts, find out if the base is local
+                ProjectionElem::Field(..)
+                    | ProjectionElem::Index(..)
+                    | ProjectionElem::ConstantIndex { .. }
+                | ProjectionElem::Subslice { .. }
+                | ProjectionElem::Downcast(..) => borrow_of_local_data(&proj.base),
+            }
+        }
+    }
+}