Finally start down the right path

This commit is contained in:
bobtwinkles 2018-03-05 02:44:10 -05:00
parent 580467d306
commit 138365368a
9 changed files with 427 additions and 431 deletions

View file

@ -18,7 +18,7 @@ use rustc_data_structures::sync::Lrc;
use super::{Context, MirBorrowckCtxt};
use super::{InitializationRequiringAction, PrefixSet};
use dataflow::{ActiveBorrows, BorrowData, FlowAtLocation, MovingOutStatements};
use dataflow::{Borrows, BorrowData, FlowAtLocation, MovingOutStatements};
use dataflow::move_paths::MovePathIndex;
use util::borrowck_errors::{BorrowckErrors, Origin};
@ -372,10 +372,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
context: Context,
borrow: &BorrowData<'tcx>,
drop_span: Span,
borrows: &ActiveBorrows<'cx, 'gcx, 'tcx>,
borrows: &Borrows<'cx, 'gcx, 'tcx>
) {
let end_span = borrows.opt_region_end_span(&borrow.region);
let scope_tree = borrows.0.scope_tree();
let scope_tree = borrows.scope_tree();
let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All)
.last()
.unwrap();

View file

@ -17,13 +17,14 @@ use rustc::mir::{BasicBlock, Location};
use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
use dataflow::{EverInitializedPlaces, MovingOutStatements};
use dataflow::{ActiveBorrows, FlowAtLocation, FlowsAtLocation};
use dataflow::{Borrows};
use dataflow::{FlowAtLocation, FlowsAtLocation};
use dataflow::move_paths::HasMoveData;
use std::fmt;
// (forced to be `pub` due to its use as an associated type below.)
pub(crate) struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
pub borrows: FlowAtLocation<ActiveBorrows<'b, 'gcx, 'tcx>>,
pub borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
pub inits: FlowAtLocation<MaybeInitializedPlaces<'b, 'gcx, 'tcx>>,
pub uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
pub move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
@ -32,7 +33,7 @@ pub(crate) struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
pub fn new(
borrows: FlowAtLocation<ActiveBorrows<'b, 'gcx, 'tcx>>,
borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
inits: FlowAtLocation<MaybeInitializedPlaces<'b, 'gcx, 'tcx>>,
uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,

View file

@ -34,11 +34,10 @@ use syntax_pos::Span;
use dataflow::{do_dataflow, DebugFormatted};
use dataflow::FlowAtLocation;
use dataflow::MoveDataParamEnv;
use dataflow::{DataflowAnalysis, DataflowResultsConsumer};
use dataflow::{DataflowResultsConsumer};
use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
use dataflow::{EverInitializedPlaces, MovingOutStatements};
use dataflow::{BorrowData, Borrows, ReserveOrActivateIndex};
use dataflow::{ActiveBorrows, Reservations};
use dataflow::indexes::BorrowIndex;
use dataflow::move_paths::{IllegalMoveOriginKind, MoveError};
use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex};
@ -54,8 +53,6 @@ mod error_reporting;
mod flows;
mod prefixes;
use std::borrow::Cow;
pub(crate) mod nll;
pub fn provide(providers: &mut Providers) {
@ -209,6 +206,18 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
};
let flow_inits = flow_inits; // remove mut
let flow_borrows = FlowAtLocation::new(do_dataflow(
tcx,
mir,
id,
&attributes,
&dead_unwinds,
Borrows::new(tcx, mir, opt_regioncx.clone(), def_id, body_id),
|rs, i| {
DebugFormatted::new(&(i.kind(), rs.location(i.borrow_index())))
}
));
let movable_generator = !match tcx.hir.get(id) {
hir::map::Node::NodeExpr(&hir::Expr {
node: hir::ExprClosure(.., Some(hir::GeneratorMovability::Static)),
@ -230,44 +239,12 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
},
access_place_error_reported: FxHashSet(),
reservation_error_reported: FxHashSet(),
nonlexical_regioncx: opt_regioncx.clone(),
nonlexical_regioncx: opt_regioncx,
nonlexical_cause_info: None,
};
let borrows = Borrows::new(tcx, mir, opt_regioncx, def_id, body_id);
let flow_reservations = do_dataflow(
tcx,
mir,
id,
&attributes,
&dead_unwinds,
Reservations::new(borrows),
|rs, i| {
// In principle we could make the dataflow ensure that
// only reservation bits show up, and assert so here.
//
// In practice it is easier to be looser; in particular,
// it is okay for the kill-sets to hold activation bits.
DebugFormatted::new(&(i.kind(), rs.location(i)))
},
);
let flow_active_borrows = {
let reservations_on_entry = flow_reservations.0.sets.entry_set_state();
let reservations = flow_reservations.0.operator;
let a = DataflowAnalysis::new_with_entry_sets(
mir,
&dead_unwinds,
Cow::Borrowed(reservations_on_entry),
ActiveBorrows::new(reservations),
);
let results = a.run(tcx, id, &attributes, |ab, i| {
DebugFormatted::new(&(i.kind(), ab.location(i)))
});
FlowAtLocation::new(results)
};
let mut state = Flows::new(
flow_active_borrows,
flow_borrows,
flow_inits,
flow_uninits,
flow_move_outs,

File diff suppressed because it is too large Load diff

View file

@ -18,7 +18,7 @@ use rustc::ty::{self, TyCtxt};
use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Terminator};
use rustc::session::Session;
use std::borrow::{Borrow, Cow};
use std::borrow::Borrow;
use std::fmt;
use std::io;
use std::mem;
@ -31,7 +31,7 @@ pub use self::impls::{DefinitelyInitializedPlaces, MovingOutStatements};
pub use self::impls::EverInitializedPlaces;
pub use self::impls::borrows::{Borrows, BorrowData};
pub use self::impls::HaveBeenBorrowedLocals;
pub(crate) use self::impls::borrows::{ActiveBorrows, Reservations, ReserveOrActivateIndex};
pub(crate) use self::impls::borrows::{ReserveOrActivateIndex};
pub use self::at_location::{FlowAtLocation, FlowsAtLocation};
pub(crate) use self::drop_flag_effects::*;
@ -584,9 +584,6 @@ impl<E:Idx> AllSets<E> {
pub fn on_entry_set_for(&self, block_idx: usize) -> &IdxSet<E> {
self.lookup_set_for(&self.on_entry_sets, block_idx)
}
pub(crate) fn entry_set_state(&self) -> &Bits<E> {
&self.on_entry_sets
}
}
/// Parameterization for the precise form of data flow that is used.
@ -739,27 +736,17 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
dead_unwinds: &'a IdxSet<mir::BasicBlock>,
denotation: D) -> Self where D: InitialFlow {
let bits_per_block = denotation.bits_per_block();
let usize_bits = mem::size_of::<usize>() * 8;
let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits;
let num_overall = Self::num_bits_overall(mir, bits_per_block);
let zeroes = Bits::new(IdxSetBuf::new_empty(num_overall));
let on_entry = Bits::new(if D::bottom_value() {
IdxSetBuf::new_filled(num_overall)
} else {
IdxSetBuf::new_empty(num_overall)
});
Self::new_with_entry_sets(mir, dead_unwinds, Cow::Owned(on_entry), denotation)
}
pub(crate) fn new_with_entry_sets(mir: &'a Mir<'tcx>,
dead_unwinds: &'a IdxSet<mir::BasicBlock>,
on_entry: Cow<Bits<D::Idx>>,
denotation: D)
-> Self {
let bits_per_block = denotation.bits_per_block();
let usize_bits = mem::size_of::<usize>() * 8;
let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits;
let num_overall = Self::num_bits_overall(mir, bits_per_block);
assert_eq!(num_overall, on_entry.bits.words().len() * usize_bits);
let zeroes = Bits::new(IdxSetBuf::new_empty(num_overall));
DataflowAnalysis {
mir,
dead_unwinds,
@ -769,13 +756,27 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
words_per_block,
gen_sets: zeroes.clone(),
kill_sets: zeroes,
on_entry_sets: on_entry.into_owned(),
on_entry_sets: on_entry,
},
operator: denotation,
}
}
}
pub fn new_from_sets(mir: &'a Mir<'tcx>,
dead_unwinds: &'a IdxSet<mir::BasicBlock>,
sets: AllSets<D::Idx>,
denotation: D) -> Self {
DataflowAnalysis {
mir,
dead_unwinds,
flow_state: DataflowState {
sets: sets,
operator: denotation,
}
}
}
fn num_bits_overall(mir: &Mir, bits_per_block: usize) -> usize {
let usize_bits = mem::size_of::<usize>() * 8;
let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits;

View file

@ -10,10 +10,12 @@
// ignore-tidy-linelength
// revisions: lxl_beyond nll_beyond nll_target
// revisions: nll_target
// The following revisions are disabled due to missing support from two-phase beyond autorefs
//[lxl_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref
//[nll_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref -Z nll
//[nll_target] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll
// This is an important corner case pointed out by Niko: one is

View file

@ -10,9 +10,13 @@
// ignore-tidy-linelength
// revisions: lxl_beyond nll_beyond nll_target
// revisions: nll_target
// The following revisions are disabled due to missing support for two_phase_beyond_autoref
//[lxl_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two_phase_beyond_autoref
//[nll_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two_phase_beyond_autoref -Z nll
//[nll_target] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll
// This is the second counter-example from Niko's blog post

View file

@ -8,10 +8,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// revisions: lxl nll g2p
// revisions: lxl nll
//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows
//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll
//[g2p]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll -Z two-phase-beyond-autoref
// the above revision is disabled until two-phase-beyond-autoref support is better
// This is a test checking that when we limit two-phase borrows to
// method receivers, we do not let other kinds of auto-ref to leak
@ -70,10 +72,8 @@ fn overloaded_call_traits() {
fn twice_ten_sm<F: FnMut(i32) -> i32>(f: &mut F) {
f(f(10));
//[lxl]~^ ERROR cannot borrow `*f` as mutable more than once at a time
//[lxl]~| ERROR cannot borrow `*f` as mutable more than once at a time
//[nll]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time
//[nll]~| ERROR cannot borrow `*f` as mutable more than once at a time
//[g2p]~^^^^^ ERROR cannot borrow `*f` as mutable more than once at a time
//[nll]~^^ ERROR cannot borrow `*f` as mutable more than once at a time
//[g2p]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time
}
fn twice_ten_si<F: Fn(i32) -> i32>(f: &mut F) {
f(f(10));
@ -88,10 +88,8 @@ fn overloaded_call_traits() {
fn twice_ten_om(f: &mut FnMut(i32) -> i32) {
f(f(10));
//[lxl]~^ ERROR cannot borrow `*f` as mutable more than once at a time
//[lxl]~| ERROR cannot borrow `*f` as mutable more than once at a time
//[nll]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time
//[nll]~| ERROR cannot borrow `*f` as mutable more than once at a time
//[g2p]~^^^^^ ERROR cannot borrow `*f` as mutable more than once at a time
//[nll]~^^ ERROR cannot borrow `*f` as mutable more than once at a time
//[g2p]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time
}
fn twice_ten_oi(f: &mut Fn(i32) -> i32) {
f(f(10));

View file

@ -12,8 +12,12 @@
// revisions: lxl_beyond nll_beyond nll_target
// The following revisions are disabled due to missing support from two-phase beyond autorefs
//[lxl_beyond]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref
//[lxl_beyond] should-fail
//[nll_beyond]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref -Z nll
//[nll_beyond] should-fail
//[nll_target]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll
// This is a corner case that the current implementation is (probably)
@ -31,10 +35,6 @@
// "nll_beyond" means the generalization of two-phase borrows to all
// `&mut`-borrows (doing so makes it easier to write code for specific
// corner cases).
//
// FIXME: in "nll_target", we currently see the same error reported
// twice. This is injected by `-Z two-phase-borrows`; not sure why as
// of yet.
fn main() {
let mut vec = vec![0, 1];
@ -49,7 +49,6 @@ fn main() {
//[lxl_beyond]~^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable
//[nll_beyond]~^^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable
//[nll_target]~^^^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable
//[nll_target]~| ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable
shared[0];
}