Skip to content

Commit d7c8c4e

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 e34e832 commit d7c8c4e

File tree

2 files changed

+25
-6
lines changed

2 files changed

+25
-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: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ use util::borrowck_errors::{BorrowckErrors, Origin};
4141
use self::MutateMode::{JustWrite, WriteAndRead};
4242

4343
use std::borrow::Cow;
44+
use std::iter;
4445

4546
pub(crate) mod nll;
4647

@@ -733,9 +734,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
733734
context,
734735
(sd, place_span.0),
735736
flow_state,
736-
|this, _index, borrow, common_prefix| match (rw, borrow.kind) {
737+
|this, index, borrow, common_prefix| match (rw, borrow.kind) {
737738
(Read(_), BorrowKind::Shared) => Control::Continue,
739+
738740
(Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut) => {
741+
// Reading from mere reservations of mutable-borrows is OK.
742+
if this.tcx.sess.opts.debugging_opts.two_phase_borrows &&
743+
index.is_reservation()
744+
{
745+
return Control::Continue;
746+
}
747+
739748
match kind {
740749
ReadKind::Copy => {
741750
error_reported = true;
@@ -1521,9 +1530,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
15211530

15221531
// check for loan restricting path P being used. Accounts for
15231532
// borrows of P, P.a.b, etc.
1524-
'next_borrow: for i in flow_state.borrows.elems_incoming() {
1525-
// FIXME for now, just skip the activation state.
1526-
if i.is_activation() { continue 'next_borrow; }
1533+
let mut elems_incoming = flow_state.borrows.elems_incoming();
1534+
'next_borrow: while let Some(i) = elems_incoming.next() {
1535+
// Skip any reservation that has a corresponding current
1536+
// activation. This way, the traversal will visit each
1537+
// borrow_index at most once.
1538+
if let Some(j) = elems_incoming.peek() {
1539+
if i.is_reservation() && j.is_activation() {
1540+
assert_eq!(i.borrow_index(), j.borrow_index());
1541+
continue 'next_borrow;
1542+
}
1543+
}
15271544

15281545
let borrowed = &data[i.borrow_index()];
15291546

@@ -2585,9 +2602,9 @@ where
25852602
self.sets.on_entry.subtract(&self.sets.kill_set);
25862603
}
25872604

2588-
fn elems_incoming(&self) -> indexed_set::Elems<BD::Idx> {
2605+
fn elems_incoming(&self) -> iter::Peekable<indexed_set::Elems<BD::Idx>> {
25892606
let univ = self.base_results.sets().bits_per_block();
2590-
self.sets.on_entry.elems(univ)
2607+
self.sets.on_entry.elems(univ).peekable()
25912608
}
25922609

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

0 commit comments

Comments
 (0)