about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/borrow_check/mod.rs7
-rw-r--r--src/librustc_mir/dataflow/impls/borrows.rs35
-rw-r--r--src/test/compile-fail/issue-25579.rs9
-rw-r--r--src/test/run-pass/borrowck/borrowck-nll-iterating-and-updating.rs (renamed from src/test/compile-fail/nll/where_clauses_in_repeat_rvalue.rs)33
4 files changed, 45 insertions, 39 deletions
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index c907c97d6d3..1e8a6792963 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -338,15 +338,10 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
 
         match stmt.kind {
             StatementKind::Assign(ref lhs, ref rhs) => {
-                // NOTE: NLL RFC calls for *shallow* write; using Deep
-                // for short-term compat w/ AST-borrowck. Also, switch
-                // to shallow requires to dataflow: "if this is an
-                // assignment `place = <rvalue>`, then any loan for some
-                // path P of which `place` is a prefix is killed."
                 self.mutate_place(
                     ContextKind::AssignLhs.new(location),
                     (lhs, span),
-                    Deep,
+                    Shallow(None),
                     JustWrite,
                     flow_state,
                 );
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index 8083c1debb8..c39ae10371c 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use rustc;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::middle::region;
@@ -362,6 +363,14 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
             }
 
             mir::StatementKind::Assign(ref lhs, ref rhs) => {
+                // Make sure there are no remaining borrows for variables
+                // that are assigned over.
+                if let Place::Local(ref local) = *lhs {
+                    // FIXME: Handle the case in which we're assigning over
+                    // a projection (`foo.bar`).
+                    self.kill_borrows_on_local(sets, local, is_activations);
+                }
+
                 // NOTE: if/when the Assign case is revised to inspect
                 // the assigned_place here, make sure to also
                 // re-consider the current implementations of the
@@ -404,16 +413,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
             mir::StatementKind::StorageDead(local) => {
                 // Make sure there are no remaining borrows for locals that
                 // are gone out of scope.
-                //
-                // FIXME: expand this to variables that are assigned over.
-                if let Some(borrow_indexes) = self.local_map.get(&local) {
-                    sets.kill_all(borrow_indexes.iter()
-                                  .map(|b| ReserveOrActivateIndex::reserved(*b)));
-                    if is_activations {
-                        sets.kill_all(borrow_indexes.iter()
-                                      .map(|b| ReserveOrActivateIndex::active(*b)));
-                    }
-                }
+                self.kill_borrows_on_local(sets, &local, is_activations)
             }
 
             mir::StatementKind::InlineAsm { .. } |
@@ -425,6 +425,21 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
         }
     }
 
+    fn kill_borrows_on_local(&self,
+                             sets: &mut BlockSets<ReserveOrActivateIndex>,
+                             local: &rustc::mir::Local,
+                             is_activations: bool)
+    {
+        if let Some(borrow_indexes) = self.local_map.get(local) {
+            sets.kill_all(borrow_indexes.iter()
+                            .map(|b| ReserveOrActivateIndex::reserved(*b)));
+            if is_activations {
+                sets.kill_all(borrow_indexes.iter()
+                                .map(|b| ReserveOrActivateIndex::active(*b)));
+            }
+        }
+    }
+
     /// Models terminator effect in Reservations and ActiveBorrows
     /// flow analyses; `is activations` tells us if we are in the
     /// latter case.
diff --git a/src/test/compile-fail/issue-25579.rs b/src/test/compile-fail/issue-25579.rs
index 5f5a58ed759..71c1d63cf5a 100644
--- a/src/test/compile-fail/issue-25579.rs
+++ b/src/test/compile-fail/issue-25579.rs
@@ -11,21 +11,22 @@
 // revisions: ast mir
 //[mir]compile-flags: -Z borrowck=mir
 
+#![feature(rustc_attrs)]
+
 enum Sexpression {
     Num(()),
     Cons(&'static mut Sexpression)
 }
 
-fn causes_ice(mut l: &mut Sexpression) {
+fn causes_error_in_ast(mut l: &mut Sexpression) {
     loop { match l {
         &mut Sexpression::Num(ref mut n) => {},
         &mut Sexpression::Cons(ref mut expr) => { //[ast]~ ERROR [E0499]
-                                                  //[mir]~^ ERROR [E0499]
             l = &mut **expr; //[ast]~ ERROR [E0506]
-                             //[mir]~^ ERROR [E0506]
         }
     }}
 }
 
-fn main() {
+#[rustc_error]
+fn main() { //[mir]~ ERROR compilation successful
 }
diff --git a/src/test/compile-fail/nll/where_clauses_in_repeat_rvalue.rs b/src/test/run-pass/borrowck/borrowck-nll-iterating-and-updating.rs
index 93c774e8996..043f1215ea5 100644
--- a/src/test/compile-fail/nll/where_clauses_in_repeat_rvalue.rs
+++ b/src/test/run-pass/borrowck/borrowck-nll-iterating-and-updating.rs
@@ -10,30 +10,25 @@
 
 // compile-flags: -Z borrowck=mir -Z nll
 
-#![allow(warnings)]
+// This example comes from the NLL RFC.
 
-struct Foo<T> {
-    t: T,
+struct List<T> {
+    value: T,
+    next: Option<Box<List<T>>>,
 }
 
-impl<T: 'static + Copy> Copy for Foo<T> {}
-impl<T: 'static + Copy> Clone for Foo<T> {
-    fn clone(&self) -> Self {
-        *self
+fn to_refs<T>(list: &mut List<T>) -> Vec<&mut T> {
+    let mut list = list;
+    let mut result = vec![];
+    loop {
+        result.push(&mut list.value);
+        if let Some(n) = list.next.as_mut() {
+            list = n;
+        } else {
+            return result;
+        }
     }
 }
 
 fn main() {
-    let mut x = 22;
-
-    {
-        let p = &x;
-        //~^ ERROR `x` does not live long enough
-        let w = Foo { t: p };
-
-        let v = [w; 22];
-    }
-
-    x += 1;
-    //~^ ERROR cannot assign to `x` because it is borrowed [E0506]
 }