Finally start down the right path
This commit is contained in:
parent
580467d306
commit
138365368a
@ -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();
|
||||
|
@ -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>>,
|
||||
|
@ -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
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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];
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user