Skip to content

Commit 6b9fbb2

Browse files
committed
fix borrows across loops, libcore *almost* compiles
1 parent 82f3fc5 commit 6b9fbb2

File tree

3 files changed

+32
-15
lines changed

3 files changed

+32
-15
lines changed

src/librustc_mir/dataflow/impls/borrows.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
4343
borrows: IndexVec<BorrowIndex, BorrowData<'tcx>>,
4444
location_map: FxHashMap<Location, BorrowIndex>,
4545
region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
46+
local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
4647
region_span_map: FxHashMap<RegionKind, Span>,
4748
nonlexical_regioncx: Option<RegionInferenceContext<'tcx>>,
4849
}
@@ -89,6 +90,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
8990
idx_vec: IndexVec::new(),
9091
location_map: FxHashMap(),
9192
region_map: FxHashMap(),
93+
local_map: FxHashMap(),
9294
region_span_map: FxHashMap()
9395
};
9496
visitor.visit_mir(mir);
@@ -99,6 +101,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
99101
root_scope,
100102
location_map: visitor.location_map,
101103
region_map: visitor.region_map,
104+
local_map: visitor.local_map,
102105
region_span_map: visitor.region_span_map,
103106
nonlexical_regioncx };
104107

@@ -108,13 +111,22 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
108111
idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
109112
location_map: FxHashMap<Location, BorrowIndex>,
110113
region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
114+
local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
111115
region_span_map: FxHashMap<RegionKind, Span>,
112116
}
113117

114118
impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
115119
fn visit_rvalue(&mut self,
116120
rvalue: &mir::Rvalue<'tcx>,
117121
location: mir::Location) {
122+
fn root_local(mut p: &mir::Place<'_>) -> Option<mir::Local> {
123+
loop { match p {
124+
mir::Place::Projection(pi) => p = &pi.base,
125+
mir::Place::Static(_) => return None,
126+
mir::Place::Local(l) => return Some(*l)
127+
}}
128+
}
129+
118130
if let mir::Rvalue::Ref(region, kind, ref place) = *rvalue {
119131
if is_unsafe_place(self.tcx, self.mir, place) { return; }
120132

@@ -123,8 +135,14 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
123135
};
124136
let idx = self.idx_vec.push(borrow);
125137
self.location_map.insert(location, idx);
138+
126139
let borrows = self.region_map.entry(region).or_insert(FxHashSet());
127140
borrows.insert(idx);
141+
142+
if let Some(local) = root_local(place) {
143+
let borrows = self.local_map.entry(local).or_insert(FxHashSet());
144+
borrows.insert(idx);
145+
}
128146
}
129147
}
130148

@@ -213,7 +231,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
213231
mir::StatementKind::EndRegion(region_scope) => {
214232
if let Some(borrow_indexes) = self.region_map.get(&ReScope(region_scope)) {
215233
assert!(self.nonlexical_regioncx.is_none());
216-
for idx in borrow_indexes { sets.kill(&idx); }
234+
sets.kill_all(borrow_indexes);
217235
} else {
218236
// (if there is no entry, then there are no borrows to be tracked)
219237
}
@@ -238,10 +256,19 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
238256
}
239257
}
240258

259+
mir::StatementKind::StorageDead(local) => {
260+
// Make sure there are no remaining borrows for locals that
261+
// are gone out of scope.
262+
//
263+
// FIXME: expand this to variables that are assigned over.
264+
if let Some(borrow_indexes) = self.local_map.get(&local) {
265+
sets.kill_all(borrow_indexes);
266+
}
267+
}
268+
241269
mir::StatementKind::InlineAsm { .. } |
242270
mir::StatementKind::SetDiscriminant { .. } |
243271
mir::StatementKind::StorageLive(..) |
244-
mir::StatementKind::StorageDead(..) |
245272
mir::StatementKind::Validate(..) |
246273
mir::StatementKind::Nop => {}
247274

src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,9 @@ fn main() {
2323
1 => { addr = &mut x; } //[ast]~ ERROR [E0499]
2424
//[mir]~^ ERROR [E0499]
2525
2 => { addr = &mut x; } //[ast]~ ERROR [E0499]
26-
//[mir]~^ ERROR [E0506]
27-
//[mir]~| ERROR [E0499]
28-
//[mir]~| ERROR [E0499]
26+
//[mir]~^ ERROR [E0499]
2927
_ => { addr = &mut x; } //[ast]~ ERROR [E0499]
30-
//[mir]~^ ERROR [E0506]
31-
//[mir]~| ERROR [E0499]
32-
//[mir]~| ERROR [E0499]
28+
//[mir]~^ ERROR [E0499]
3329
}
3430
}
3531
}
36-
37-

src/test/compile-fail/issue-25579.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,9 @@ fn causes_ice(mut l: &mut Sexpression) {
2020
loop { match l {
2121
&mut Sexpression::Num(ref mut n) => {},
2222
&mut Sexpression::Cons(ref mut expr) => { //[ast]~ ERROR [E0499]
23-
//[mir]~^ ERROR [E0506]
24-
//[mir]~| ERROR [E0499]
23+
//[mir]~^ ERROR [E0499]
2524
l = &mut **expr; //[ast]~ ERROR [E0506]
2625
//[mir]~^ ERROR [E0506]
27-
//[mir]~| ERROR [E0499]
28-
//[mir]~| ERROR [E0506]
29-
//[mir]~| ERROR [E0499]
3026
}
3127
}}
3228
}

0 commit comments

Comments
 (0)