Skip to content

Commit 3621645

Browse files
committed
Incorporate active-borrows dataflow into MIR borrow check, yielding
two-phase `&mut`-borrow support. This (new) support sits under `-Z two-phase-borrows` debugflag. (Still needs tests. That's coming next.)
1 parent 1334638 commit 3621645

File tree

3 files changed

+26
-6
lines changed

3 files changed

+26
-6
lines changed

src/librustc/session/config.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
10111011
"emit EndRegion as part of MIR; enable transforms that solely process EndRegion"),
10121012
borrowck: Option<String> = (None, parse_opt_string, [UNTRACKED],
10131013
"select which borrowck is used (`ast`, `mir`, or `compare`)"),
1014+
two_phase_borrows: bool = (false, parse_bool, [UNTRACKED],
1015+
"use two-phase reserved/active distinction for `&mut` borrows in MIR borrowck"),
10141016
time_passes: bool = (false, parse_bool, [UNTRACKED],
10151017
"measure time of each rustc pass"),
10161018
count_llvm_insns: bool = (false, parse_bool,

src/librustc_mir/borrow_check/mod.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -701,9 +701,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
701701
context,
702702
(sd, place_span.0),
703703
flow_state,
704-
|this, _index, borrow| match (rw, borrow.kind) {
704+
|this, index, borrow| match (rw, borrow.kind) {
705705
(Read(_), BorrowKind::Shared) => Control::Continue,
706+
706707
(Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut) => {
708+
// Reading from mere reservations of mutable-borrows is OK.
709+
if this.tcx.sess.opts.debugging_opts.two_phase_borrows &&
710+
index.is_reservation()
711+
{
712+
return Control::Continue;
713+
}
714+
707715
match kind {
708716
ReadKind::Copy => {
709717
error_reported = true;
@@ -1826,9 +1834,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
18261834

18271835
// check for loan restricting path P being used. Accounts for
18281836
// borrows of P, P.a.b, etc.
1829-
for i in flow_state.borrows.elems_incoming() {
1830-
// FIXME for now, just skip the activation state.
1831-
if i.is_activation() { continue }
1837+
let mut elems_incoming = flow_state.borrows.elems_incoming();
1838+
while let Some(i) = elems_incoming.next() {
1839+
// Skip any reservation that has a corresponding current
1840+
// activation. This way, the traversal will visit each
1841+
// borrow_index at most once.
1842+
if let Some(j) = elems_incoming.peek() {
1843+
if i.is_reservation() && j.is_activation() {
1844+
assert_eq!(i.borrow_index(), j.borrow_index());
1845+
continue;
1846+
}
1847+
}
18321848

18331849
let borrowed = &data[i.borrow_index()];
18341850

src/librustc_mir/dataflow/at_location.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ use rustc_data_structures::indexed_vec::Idx;
1818
use dataflow::{BitDenotation, BlockSets, DataflowResults};
1919
use dataflow::move_paths::{HasMoveData, MovePathIndex};
2020

21+
use std::iter;
22+
2123
/// A trait for "cartesian products" of multiple FlowAtLocation.
2224
///
2325
/// There's probably a way to auto-impl this, but I think
@@ -94,9 +96,9 @@ where
9496
self.curr_state.contains(x)
9597
}
9698

97-
pub fn elems_incoming(&self) -> indexed_set::Elems<BD::Idx> {
99+
pub fn elems_incoming(&self) -> iter::Peekable<indexed_set::Elems<BD::Idx>> {
98100
let univ = self.base_results.sets().bits_per_block();
99-
self.curr_state.elems(univ)
101+
self.curr_state.elems(univ).peekable()
100102
}
101103

102104
pub fn with_elems_outgoing<F>(&self, f: F)

0 commit comments

Comments
 (0)