about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <ariel.byd@gmail.com>2017-12-04 13:21:28 +0200
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2017-12-06 00:34:02 +0200
commit6b9fbb2ab85914820da703182a5c51acf59088cf (patch)
tree639e973658bc7dd681d2b048946005d713fe8994
parent82f3fc5dbca4d2d696ce66b902cb339f4507ae9f (diff)
downloadrust-6b9fbb2ab85914820da703182a5c51acf59088cf.tar.gz
rust-6b9fbb2ab85914820da703182a5c51acf59088cf.zip
fix borrows across loops, libcore *almost* compiles
-rw-r--r--src/librustc_mir/dataflow/impls/borrows.rs31
-rw-r--r--src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs10
-rw-r--r--src/test/compile-fail/issue-25579.rs6
3 files changed, 32 insertions, 15 deletions
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index b3b06f7f6cd..c27cb43eff7 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -43,6 +43,7 @@ pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
     borrows: IndexVec<BorrowIndex, BorrowData<'tcx>>,
     location_map: FxHashMap<Location, BorrowIndex>,
     region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
+    local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
     region_span_map: FxHashMap<RegionKind, Span>,
     nonlexical_regioncx: Option<RegionInferenceContext<'tcx>>,
 }
@@ -89,6 +90,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
             idx_vec: IndexVec::new(),
             location_map: FxHashMap(),
             region_map: FxHashMap(),
+            local_map: FxHashMap(),
             region_span_map: FxHashMap()
         };
         visitor.visit_mir(mir);
@@ -99,6 +101,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
                          root_scope,
                          location_map: visitor.location_map,
                          region_map: visitor.region_map,
+                         local_map: visitor.local_map,
                          region_span_map: visitor.region_span_map,
                          nonlexical_regioncx };
 
@@ -108,6 +111,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
             idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
             location_map: FxHashMap<Location, BorrowIndex>,
             region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
+            local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
             region_span_map: FxHashMap<RegionKind, Span>,
         }
 
@@ -115,6 +119,14 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
             fn visit_rvalue(&mut self,
                             rvalue: &mir::Rvalue<'tcx>,
                             location: mir::Location) {
+                fn root_local(mut p: &mir::Place<'_>) -> Option<mir::Local> {
+                    loop { match p {
+                        mir::Place::Projection(pi) => p = &pi.base,
+                        mir::Place::Static(_) => return None,
+                        mir::Place::Local(l) => return Some(*l)
+                    }}
+                }
+
                 if let mir::Rvalue::Ref(region, kind, ref place) = *rvalue {
                     if is_unsafe_place(self.tcx, self.mir, place) { return; }
 
@@ -123,8 +135,14 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
                     };
                     let idx = self.idx_vec.push(borrow);
                     self.location_map.insert(location, idx);
+
                     let borrows = self.region_map.entry(region).or_insert(FxHashSet());
                     borrows.insert(idx);
+
+                    if let Some(local) = root_local(place) {
+                        let borrows = self.local_map.entry(local).or_insert(FxHashSet());
+                        borrows.insert(idx);
+                    }
                 }
             }
 
@@ -213,7 +231,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
             mir::StatementKind::EndRegion(region_scope) => {
                 if let Some(borrow_indexes) = self.region_map.get(&ReScope(region_scope)) {
                     assert!(self.nonlexical_regioncx.is_none());
-                    for idx in borrow_indexes { sets.kill(&idx); }
+                    sets.kill_all(borrow_indexes);
                 } else {
                     // (if there is no entry, then there are no borrows to be tracked)
                 }
@@ -238,10 +256,19 @@ impl<'a, 'gcx, 'tcx> BitDenotation for 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);
+                }
+            }
+
             mir::StatementKind::InlineAsm { .. } |
             mir::StatementKind::SetDiscriminant { .. } |
             mir::StatementKind::StorageLive(..) |
-            mir::StatementKind::StorageDead(..) |
             mir::StatementKind::Validate(..) |
             mir::StatementKind::Nop => {}
 
diff --git a/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs b/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs
index 6896d166e7a..63bb04a0e4c 100644
--- a/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs
+++ b/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs
@@ -23,15 +23,9 @@ fn main() {
             1 => { addr = &mut x; } //[ast]~ ERROR [E0499]
             //[mir]~^ ERROR [E0499]
             2 => { addr = &mut x; } //[ast]~ ERROR [E0499]
-            //[mir]~^ ERROR [E0506]
-            //[mir]~| ERROR [E0499]
-            //[mir]~| ERROR [E0499]
+            //[mir]~^ ERROR [E0499]
             _ => { addr = &mut x; } //[ast]~ ERROR [E0499]
-            //[mir]~^ ERROR [E0506]
-            //[mir]~| ERROR [E0499]
-            //[mir]~| ERROR [E0499]
+            //[mir]~^ ERROR [E0499]
         }
     }
 }
-
-
diff --git a/src/test/compile-fail/issue-25579.rs b/src/test/compile-fail/issue-25579.rs
index b4a5cd72d86..5f5a58ed759 100644
--- a/src/test/compile-fail/issue-25579.rs
+++ b/src/test/compile-fail/issue-25579.rs
@@ -20,13 +20,9 @@ fn causes_ice(mut l: &mut Sexpression) {
     loop { match l {
         &mut Sexpression::Num(ref mut n) => {},
         &mut Sexpression::Cons(ref mut expr) => { //[ast]~ ERROR [E0499]
-                                                  //[mir]~^ ERROR [E0506]
-                                                  //[mir]~| ERROR [E0499]
+                                                  //[mir]~^ ERROR [E0499]
             l = &mut **expr; //[ast]~ ERROR [E0506]
                              //[mir]~^ ERROR [E0506]
-                             //[mir]~| ERROR [E0499]
-                             //[mir]~| ERROR [E0506]
-                             //[mir]~| ERROR [E0499]
         }
     }}
 }