Skip to content

Commit 84feab3

Browse files
committed
Auto merge of #46537 - pnkfelix:two-phase-borrows, r=arielb1
[MIR-borrowck] Two phase borrows This adds limited support for two-phase borrows as described in http://smallcultfollowing.com/babysteps/blog/2017/03/01/nested-method-calls-via-two-phase-borrowing/ The support is off by default; you opt into it via the flag `-Z two-phase-borrows` I have written "*limited* support" above because there are simple variants of the simple `v.push(v.len())` example that one would think should work but currently do not, such as the one documented in the test compile-fail/borrowck/two-phase-reservation-sharing-interference-2.rs (To be clear, that test is not describing something that is unsound. It is just providing an explicit example of a limitation in the implementation given in this PR. I have ideas on how to fix, but I want to land the work that is in this PR first, so that I can stop repeatedly rebasing this branch.)
2 parents 9331031 + 159037e commit 84feab3

25 files changed

+1182
-255
lines changed

src/librustc/mir/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1137,7 +1137,7 @@ impl<'tcx> Debug for Statement<'tcx> {
11371137

11381138
/// A path to a value; something that can be evaluated without
11391139
/// changing or disturbing program state.
1140-
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
1140+
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
11411141
pub enum Place<'tcx> {
11421142
/// local variable
11431143
Local(Local),
@@ -1151,7 +1151,7 @@ pub enum Place<'tcx> {
11511151

11521152
/// The def-id of a static, along with its normalized type (which is
11531153
/// stored to avoid requiring normalization when reading MIR).
1154-
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
1154+
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
11551155
pub struct Static<'tcx> {
11561156
pub def_id: DefId,
11571157
pub ty: Ty<'tcx>,

src/librustc/session/config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
10281028
"emit EndRegion as part of MIR; enable transforms that solely process EndRegion"),
10291029
borrowck: Option<String> = (None, parse_opt_string, [UNTRACKED],
10301030
"select which borrowck is used (`ast`, `mir`, or `compare`)"),
1031+
two_phase_borrows: bool = (false, parse_bool, [UNTRACKED],
1032+
"use two-phase reserved/active distinction for `&mut` borrows in MIR borrowck"),
10311033
time_passes: bool = (false, parse_bool, [UNTRACKED],
10321034
"measure time of each rustc pass"),
10331035
count_llvm_insns: bool = (false, parse_bool,

src/librustc_data_structures/indexed_set.rs

+20
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use std::borrow::{Borrow, BorrowMut, ToOwned};
1112
use std::fmt;
1213
use std::iter;
1314
use std::marker::PhantomData;
@@ -73,6 +74,25 @@ pub struct IdxSet<T: Idx> {
7374
bits: [Word],
7475
}
7576

77+
impl<T: Idx> Borrow<IdxSet<T>> for IdxSetBuf<T> {
78+
fn borrow(&self) -> &IdxSet<T> {
79+
&*self
80+
}
81+
}
82+
83+
impl<T: Idx> BorrowMut<IdxSet<T>> for IdxSetBuf<T> {
84+
fn borrow_mut(&mut self) -> &mut IdxSet<T> {
85+
&mut *self
86+
}
87+
}
88+
89+
impl<T: Idx> ToOwned for IdxSet<T> {
90+
type Owned = IdxSetBuf<T>;
91+
fn to_owned(&self) -> Self::Owned {
92+
IdxSet::to_owned(self)
93+
}
94+
}
95+
7696
impl<T: Idx> fmt::Debug for IdxSetBuf<T> {
7797
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
7898
w.debug_list()

src/librustc_driver/pretty.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -423,24 +423,28 @@ impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
423423
pprust_hir::NodeName(_) => Ok(()),
424424
pprust_hir::NodeItem(item) => {
425425
s.s.space()?;
426-
s.synth_comment(item.id.to_string())
426+
s.synth_comment(format!("node_id: {} hir local_id: {}",
427+
item.id, item.hir_id.local_id.0))
427428
}
428429
pprust_hir::NodeSubItem(id) => {
429430
s.s.space()?;
430431
s.synth_comment(id.to_string())
431432
}
432433
pprust_hir::NodeBlock(blk) => {
433434
s.s.space()?;
434-
s.synth_comment(format!("block {}", blk.id))
435+
s.synth_comment(format!("block node_id: {} hir local_id: {}",
436+
blk.id, blk.hir_id.local_id.0))
435437
}
436438
pprust_hir::NodeExpr(expr) => {
437439
s.s.space()?;
438-
s.synth_comment(expr.id.to_string())?;
440+
s.synth_comment(format!("node_id: {} hir local_id: {}",
441+
expr.id, expr.hir_id.local_id.0))?;
439442
s.pclose()
440443
}
441444
pprust_hir::NodePat(pat) => {
442445
s.s.space()?;
443-
s.synth_comment(format!("pat {}", pat.id))
446+
s.synth_comment(format!("pat node_id: {} hir local_id: {}",
447+
pat.id, pat.hir_id.local_id.0))
444448
}
445449
}
446450
}

src/librustc_mir/borrow_check/error_reporting.rs

+11-14
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
use syntax_pos::Span;
1212
use rustc::middle::region::ScopeTree;
1313
use rustc::mir::{BorrowKind, Field, Local, Location, Operand};
14-
use rustc::mir::{Place, ProjectionElem, Rvalue, StatementKind};
14+
use rustc::mir::{Place, ProjectionElem, Rvalue, Statement, StatementKind};
1515
use rustc::ty::{self, RegionKind};
1616
use rustc_data_structures::indexed_vec::Idx;
1717

1818
use std::rc::Rc;
1919

2020
use super::{MirBorrowckCtxt, Context};
2121
use super::{InitializationRequiringAction, PrefixSet};
22-
use dataflow::{BorrowData, Borrows, FlowAtLocation, MovingOutStatements};
22+
use dataflow::{ActiveBorrows, BorrowData, FlowAtLocation, MovingOutStatements};
2323
use dataflow::move_paths::MovePathIndex;
2424
use util::borrowck_errors::{BorrowckErrors, Origin};
2525

@@ -96,7 +96,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
9696
Some(name) => format!("`{}`", name),
9797
None => "value".to_owned(),
9898
};
99-
let borrow_msg = match self.describe_place(&borrow.place) {
99+
let borrow_msg = match self.describe_place(&borrow.borrowed_place) {
100100
Some(name) => format!("`{}`", name),
101101
None => "value".to_owned(),
102102
};
@@ -124,7 +124,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
124124
span,
125125
&self.describe_place(place).unwrap_or("_".to_owned()),
126126
self.retrieve_borrow_span(borrow),
127-
&self.describe_place(&borrow.place).unwrap_or("_".to_owned()),
127+
&self.describe_place(&borrow.borrowed_place).unwrap_or("_".to_owned()),
128128
Origin::Mir,
129129
);
130130

@@ -143,12 +143,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
143143
use rustc::hir::ExprClosure;
144144
use rustc::mir::AggregateKind;
145145

146-
let local = if let StatementKind::Assign(Place::Local(local), _) =
147-
self.mir[location.block].statements[location.statement_index].kind
148-
{
149-
local
150-
} else {
151-
return None;
146+
let local = match self.mir[location.block].statements.get(location.statement_index) {
147+
Some(&Statement { kind: StatementKind::Assign(Place::Local(local), _), .. }) => local,
148+
_ => return None,
152149
};
153150

154151
for stmt in &self.mir[location.block].statements[location.statement_index + 1..] {
@@ -324,11 +321,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
324321
_: Context,
325322
borrow: &BorrowData<'tcx>,
326323
drop_span: Span,
327-
borrows: &Borrows<'cx, 'gcx, 'tcx>
324+
borrows: &ActiveBorrows<'cx, 'gcx, 'tcx>
328325
) {
329326
let end_span = borrows.opt_region_end_span(&borrow.region);
330-
let scope_tree = borrows.scope_tree();
331-
let root_place = self.prefixes(&borrow.place, PrefixSet::All).last().unwrap();
327+
let scope_tree = borrows.0.scope_tree();
328+
let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All).last().unwrap();
332329

333330
match root_place {
334331
&Place::Local(local) => {
@@ -357,7 +354,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
357354
_ => drop_span,
358355
};
359356

360-
match (borrow.region, &self.describe_place(&borrow.place)) {
357+
match (borrow.region, &self.describe_place(&borrow.borrowed_place)) {
361358
(RegionKind::ReScope(_), Some(name)) => {
362359
self.report_scoped_local_value_does_not_live_long_enough(
363360
name, &scope_tree, &borrow, drop_span, borrow_span, proper_span, end_span);

src/librustc_mir/borrow_check/flows.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ use rustc::mir::{BasicBlock, Location};
1717

1818
use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
1919
use dataflow::{EverInitializedLvals, MovingOutStatements};
20-
use dataflow::{Borrows, FlowAtLocation, FlowsAtLocation};
20+
use dataflow::{ActiveBorrows, FlowAtLocation, FlowsAtLocation};
2121
use dataflow::move_paths::HasMoveData;
2222
use std::fmt;
2323

2424
// (forced to be `pub` due to its use as an associated type below.)
25-
pub struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
26-
pub borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
25+
pub(crate) struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
26+
pub borrows: FlowAtLocation<ActiveBorrows<'b, 'gcx, 'tcx>>,
2727
pub inits: FlowAtLocation<MaybeInitializedLvals<'b, 'gcx, 'tcx>>,
2828
pub uninits: FlowAtLocation<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>,
2929
pub move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
@@ -32,7 +32,7 @@ pub struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
3232

3333
impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
3434
pub fn new(
35-
borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
35+
borrows: FlowAtLocation<ActiveBorrows<'b, 'gcx, 'tcx>>,
3636
inits: FlowAtLocation<MaybeInitializedLvals<'b, 'gcx, 'tcx>>,
3737
uninits: FlowAtLocation<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>,
3838
move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
@@ -87,7 +87,7 @@ impl<'b, 'gcx, 'tcx> fmt::Display for Flows<'b, 'gcx, 'tcx> {
8787
s.push_str(", ");
8888
};
8989
saw_one = true;
90-
let borrow_data = &self.borrows.operator().borrows()[borrow];
90+
let borrow_data = &self.borrows.operator().borrows()[borrow.borrow_index()];
9191
s.push_str(&format!("{}", borrow_data));
9292
});
9393
s.push_str("] ");
@@ -99,7 +99,7 @@ impl<'b, 'gcx, 'tcx> fmt::Display for Flows<'b, 'gcx, 'tcx> {
9999
s.push_str(", ");
100100
};
101101
saw_one = true;
102-
let borrow_data = &self.borrows.operator().borrows()[borrow];
102+
let borrow_data = &self.borrows.operator().borrows()[borrow.borrow_index()];
103103
s.push_str(&format!("{}", borrow_data));
104104
});
105105
s.push_str("] ");

0 commit comments

Comments
 (0)