about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-12-04 10:03:34 -0500
committerNiko Matsakis <niko@alum.mit.edu>2019-01-02 14:44:25 -0500
commit5efcff11a4695fd547bf07f2b003acc20645071f (patch)
treeecccdf0b43874fc8ae4034853c75985c0fc7782d
parentec194646fef1a467073ad74b8b68f6f202cfce97 (diff)
downloadrust-5efcff11a4695fd547bf07f2b003acc20645071f.tar.gz
rust-5efcff11a4695fd547bf07f2b003acc20645071f.zip
generate invalidations from 2-phase-borrow activations
-rw-r--r--src/librustc_mir/borrow_check/nll/invalidation.rs50
1 files changed, 46 insertions, 4 deletions
diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs
index 76b516246f9..112b3995255 100644
--- a/src/librustc_mir/borrow_check/nll/invalidation.rs
+++ b/src/librustc_mir/borrow_check/nll/invalidation.rs
@@ -56,10 +56,14 @@ struct InvalidationGenerator<'cx, 'tcx: 'cx, 'gcx: 'tcx> {
 /// Visits the whole MIR and generates invalidates() facts
 /// Most of the code implementing this was stolen from borrow_check/mod.rs
 impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
-    fn visit_statement(&mut self,
-                       block: BasicBlock,
-                       statement: &Statement<'tcx>,
-                       location: Location) {
+    fn visit_statement(
+        &mut self,
+        block: BasicBlock,
+        statement: &Statement<'tcx>,
+        location: Location,
+    ) {
+        self.check_activations(location);
+
         match statement.kind {
             StatementKind::Assign(ref lhs, ref rhs) => {
                 self.consume_rvalue(
@@ -148,6 +152,8 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
         terminator: &Terminator<'tcx>,
         location: Location
     ) {
+        self.check_activations(location);
+
         match terminator.kind {
             TerminatorKind::SwitchInt {
                 ref discr,
@@ -471,5 +477,41 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
         let lidx = self.location_table.start_index(l);
         self.all_facts.invalidates.push((lidx, b));
     }
+
+    fn check_activations(
+        &mut self,
+        location: Location,
+    ) {
+        if !self.tcx.two_phase_borrows() {
+            return;
+        }
+
+        // Two-phase borrow support: For each activation that is newly
+        // generated at this statement, check if it interferes with
+        // another borrow.
+        for &borrow_index in self.borrow_set.activations_at_location(location) {
+            let borrow = &self.borrow_set[borrow_index];
+
+            // only mutable borrows should be 2-phase
+            assert!(match borrow.kind {
+                BorrowKind::Shared | BorrowKind::Shallow => false,
+                BorrowKind::Unique | BorrowKind::Mut { .. } => true,
+            });
+
+            self.access_place(
+                ContextKind::Activation.new(location),
+                &borrow.borrowed_place,
+                (
+                    Deep,
+                    Activation(WriteKind::MutableBorrow(borrow.kind), borrow_index),
+                ),
+                LocalMutationIsAllowed::No,
+            );
+
+            // We do not need to call `check_if_path_or_subpath_is_moved`
+            // again, as we already called it when we made the
+            // initial reservation.
+        }
+    }
 }