From 6b9fbb2ab85914820da703182a5c51acf59088cf Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Mon, 4 Dec 2017 13:21:28 +0200 Subject: [PATCH] fix borrows across loops, libcore *almost* compiles --- src/librustc_mir/dataflow/impls/borrows.rs | 31 +++++++++++++++++-- .../borrowck-mut-borrow-linear-errors.rs | 10 ++---- src/test/compile-fail/issue-25579.rs | 6 +--- 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 b3b06f7f6cdb0..c27cb43eff77b 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>, location_map: FxHashMap, region_map: FxHashMap, FxHashSet>, + local_map: FxHashMap>, region_span_map: FxHashMap, nonlexical_regioncx: Option>, } @@ -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>, location_map: FxHashMap, region_map: FxHashMap, FxHashSet>, + local_map: FxHashMap>, region_span_map: FxHashMap, } @@ -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 { + 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 6896d166e7a4a..63bb04a0e4c3a 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 b4a5cd72d86de..5f5a58ed75942 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] } }} }