Skip to content

Commit

Permalink
Auto merge of #46537 - pnkfelix:two-phase-borrows, r=arielb1
Browse files Browse the repository at this point in the history
[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.)
  • Loading branch information
bors committed Dec 15, 2017
2 parents 9331031 + 159037e commit 84feab3
Show file tree
Hide file tree
Showing 25 changed files with 1,182 additions and 255 deletions.
4 changes: 2 additions & 2 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1137,7 +1137,7 @@ impl<'tcx> Debug for Statement<'tcx> {

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

/// The def-id of a static, along with its normalized type (which is
/// stored to avoid requiring normalization when reading MIR).
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct Static<'tcx> {
pub def_id: DefId,
pub ty: Ty<'tcx>,
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1028,6 +1028,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"emit EndRegion as part of MIR; enable transforms that solely process EndRegion"),
borrowck: Option<String> = (None, parse_opt_string, [UNTRACKED],
"select which borrowck is used (`ast`, `mir`, or `compare`)"),
two_phase_borrows: bool = (false, parse_bool, [UNTRACKED],
"use two-phase reserved/active distinction for `&mut` borrows in MIR borrowck"),
time_passes: bool = (false, parse_bool, [UNTRACKED],
"measure time of each rustc pass"),
count_llvm_insns: bool = (false, parse_bool,
Expand Down
20 changes: 20 additions & 0 deletions src/librustc_data_structures/indexed_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::borrow::{Borrow, BorrowMut, ToOwned};
use std::fmt;
use std::iter;
use std::marker::PhantomData;
Expand Down Expand Up @@ -73,6 +74,25 @@ pub struct IdxSet<T: Idx> {
bits: [Word],
}

impl<T: Idx> Borrow<IdxSet<T>> for IdxSetBuf<T> {
fn borrow(&self) -> &IdxSet<T> {
&*self
}
}

impl<T: Idx> BorrowMut<IdxSet<T>> for IdxSetBuf<T> {
fn borrow_mut(&mut self) -> &mut IdxSet<T> {
&mut *self
}
}

impl<T: Idx> ToOwned for IdxSet<T> {
type Owned = IdxSetBuf<T>;
fn to_owned(&self) -> Self::Owned {
IdxSet::to_owned(self)
}
}

impl<T: Idx> fmt::Debug for IdxSetBuf<T> {
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
w.debug_list()
Expand Down
12 changes: 8 additions & 4 deletions src/librustc_driver/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,24 +423,28 @@ impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
pprust_hir::NodeName(_) => Ok(()),
pprust_hir::NodeItem(item) => {
s.s.space()?;
s.synth_comment(item.id.to_string())
s.synth_comment(format!("node_id: {} hir local_id: {}",
item.id, item.hir_id.local_id.0))
}
pprust_hir::NodeSubItem(id) => {
s.s.space()?;
s.synth_comment(id.to_string())
}
pprust_hir::NodeBlock(blk) => {
s.s.space()?;
s.synth_comment(format!("block {}", blk.id))
s.synth_comment(format!("block node_id: {} hir local_id: {}",
blk.id, blk.hir_id.local_id.0))
}
pprust_hir::NodeExpr(expr) => {
s.s.space()?;
s.synth_comment(expr.id.to_string())?;
s.synth_comment(format!("node_id: {} hir local_id: {}",
expr.id, expr.hir_id.local_id.0))?;
s.pclose()
}
pprust_hir::NodePat(pat) => {
s.s.space()?;
s.synth_comment(format!("pat {}", pat.id))
s.synth_comment(format!("pat node_id: {} hir local_id: {}",
pat.id, pat.hir_id.local_id.0))
}
}
}
Expand Down
25 changes: 11 additions & 14 deletions src/librustc_mir/borrow_check/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
use syntax_pos::Span;
use rustc::middle::region::ScopeTree;
use rustc::mir::{BorrowKind, Field, Local, Location, Operand};
use rustc::mir::{Place, ProjectionElem, Rvalue, StatementKind};
use rustc::mir::{Place, ProjectionElem, Rvalue, Statement, StatementKind};
use rustc::ty::{self, RegionKind};
use rustc_data_structures::indexed_vec::Idx;

use std::rc::Rc;

use super::{MirBorrowckCtxt, Context};
use super::{InitializationRequiringAction, PrefixSet};
use dataflow::{BorrowData, Borrows, FlowAtLocation, MovingOutStatements};
use dataflow::{ActiveBorrows, BorrowData, FlowAtLocation, MovingOutStatements};
use dataflow::move_paths::MovePathIndex;
use util::borrowck_errors::{BorrowckErrors, Origin};

Expand Down Expand Up @@ -96,7 +96,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
Some(name) => format!("`{}`", name),
None => "value".to_owned(),
};
let borrow_msg = match self.describe_place(&borrow.place) {
let borrow_msg = match self.describe_place(&borrow.borrowed_place) {
Some(name) => format!("`{}`", name),
None => "value".to_owned(),
};
Expand Down Expand Up @@ -124,7 +124,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
span,
&self.describe_place(place).unwrap_or("_".to_owned()),
self.retrieve_borrow_span(borrow),
&self.describe_place(&borrow.place).unwrap_or("_".to_owned()),
&self.describe_place(&borrow.borrowed_place).unwrap_or("_".to_owned()),
Origin::Mir,
);

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

let local = if let StatementKind::Assign(Place::Local(local), _) =
self.mir[location.block].statements[location.statement_index].kind
{
local
} else {
return None;
let local = match self.mir[location.block].statements.get(location.statement_index) {
Some(&Statement { kind: StatementKind::Assign(Place::Local(local), _), .. }) => local,
_ => return None,
};

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

match root_place {
&Place::Local(local) => {
Expand Down Expand Up @@ -357,7 +354,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
_ => drop_span,
};

match (borrow.region, &self.describe_place(&borrow.place)) {
match (borrow.region, &self.describe_place(&borrow.borrowed_place)) {
(RegionKind::ReScope(_), Some(name)) => {
self.report_scoped_local_value_does_not_live_long_enough(
name, &scope_tree, &borrow, drop_span, borrow_span, proper_span, end_span);
Expand Down
12 changes: 6 additions & 6 deletions src/librustc_mir/borrow_check/flows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ use rustc::mir::{BasicBlock, Location};

use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
use dataflow::{EverInitializedLvals, MovingOutStatements};
use dataflow::{Borrows, FlowAtLocation, FlowsAtLocation};
use dataflow::{ActiveBorrows, FlowAtLocation, FlowsAtLocation};
use dataflow::move_paths::HasMoveData;
use std::fmt;

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

impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
pub fn new(
borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
borrows: FlowAtLocation<ActiveBorrows<'b, 'gcx, 'tcx>>,
inits: FlowAtLocation<MaybeInitializedLvals<'b, 'gcx, 'tcx>>,
uninits: FlowAtLocation<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>,
move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
Expand Down Expand Up @@ -87,7 +87,7 @@ impl<'b, 'gcx, 'tcx> fmt::Display for Flows<'b, 'gcx, 'tcx> {
s.push_str(", ");
};
saw_one = true;
let borrow_data = &self.borrows.operator().borrows()[borrow];
let borrow_data = &self.borrows.operator().borrows()[borrow.borrow_index()];
s.push_str(&format!("{}", borrow_data));
});
s.push_str("] ");
Expand All @@ -99,7 +99,7 @@ impl<'b, 'gcx, 'tcx> fmt::Display for Flows<'b, 'gcx, 'tcx> {
s.push_str(", ");
};
saw_one = true;
let borrow_data = &self.borrows.operator().borrows()[borrow];
let borrow_data = &self.borrows.operator().borrows()[borrow.borrow_index()];
s.push_str(&format!("{}", borrow_data));
});
s.push_str("] ");
Expand Down
Loading

0 comments on commit 84feab3

Please sign in to comment.