Skip to content

Commit 43d649e

Browse files
committed
Auto merge of #65672 - ecstatic-morse:unified-dataflow-proto, r=<try>
[WIP] A single framework for gen-kill and generic dataflow problems This is the prototype implementation discussed in rust-lang/compiler-team#202. You can read a high-level description of it in [the proposal](https://hackmd.io/@39Qr_z9cQhasi25sGjmFnA/Skvd9rztS) for that design meeting. This would eventually supersede the existing `BitDenotation` interface. r? @ghost cc @rust-lang/compiler (esp. @eddyb and @pnkfelix)
2 parents cefcc20 + dceb654 commit 43d649e

File tree

24 files changed

+1945
-826
lines changed

24 files changed

+1945
-826
lines changed

src/librustc/mir/mod.rs

+25
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,31 @@ impl<'tcx> Body<'tcx> {
204204
}
205205
}
206206

207+
/// Returns a partially initialized MIR body containing only a list of basic blocks.
208+
///
209+
/// The returned MIR contains no `LocalDecl`s (even for the return place) or source scopes. It
210+
/// is only useful for testing but cannot be `#[cfg(test)]` because it is used in a different
211+
/// crate.
212+
pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
213+
Body {
214+
phase: MirPhase::Build,
215+
basic_blocks,
216+
source_scopes: IndexVec::new(),
217+
source_scope_local_data: ClearCrossCrate::Clear,
218+
yield_ty: None,
219+
generator_drop: None,
220+
generator_layout: None,
221+
local_decls: IndexVec::new(),
222+
user_type_annotations: IndexVec::new(),
223+
arg_count: 0,
224+
__upvar_debuginfo_codegen_only_do_not_use: Vec::new(),
225+
spread_arg: None,
226+
span: syntax_pos::DUMMY_SP,
227+
cache: cache::Cache::new(),
228+
control_flow_destroyed: Vec::new(),
229+
}
230+
}
231+
207232
#[inline]
208233
pub fn basic_blocks(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
209234
&self.basic_blocks

src/librustc_mir/borrow_check/mod.rs

+6-11
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use crate::dataflow::Borrows;
3737
use crate::dataflow::DataflowResultsConsumer;
3838
use crate::dataflow::FlowAtLocation;
3939
use crate::dataflow::MoveDataParamEnv;
40-
use crate::dataflow::{do_dataflow, DebugFormatted};
40+
use crate::dataflow::{self, do_dataflow, DebugFormatted};
4141
use crate::dataflow::EverInitializedPlaces;
4242
use crate::dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
4343

@@ -167,16 +167,10 @@ fn do_mir_borrowck<'a, 'tcx>(
167167
param_env,
168168
};
169169

170-
let dead_unwinds = BitSet::new_empty(body.basic_blocks().len());
171-
let mut flow_inits = FlowAtLocation::new(do_dataflow(
172-
tcx,
173-
body,
174-
def_id,
175-
&attributes,
176-
&dead_unwinds,
177-
MaybeInitializedPlaces::new(tcx, body, &mdpe),
178-
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
179-
));
170+
let flow_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe);
171+
let mut flow_inits = dataflow::generic::Engine::new_gen_kill(tcx, body, def_id, flow_inits)
172+
.iterate_to_fixpoint()
173+
.into_cursor(body);
180174

181175
let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(id).is_fn_or_closure();
182176
let borrow_set = Rc::new(BorrowSet::build(
@@ -205,6 +199,7 @@ fn do_mir_borrowck<'a, 'tcx>(
205199

206200
let regioncx = Rc::new(regioncx);
207201

202+
let dead_unwinds = BitSet::new_empty(body.basic_blocks().len());
208203
let flow_borrows = FlowAtLocation::new(do_dataflow(
209204
tcx,
210205
body,

src/librustc_mir/borrow_check/nll/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ use crate::borrow_check::location::{LocationIndex, LocationTable};
33
use crate::borrow_check::nll::facts::AllFactsExt;
44
use crate::borrow_check::nll::type_check::{MirTypeckResults, MirTypeckRegionConstraints};
55
use crate::borrow_check::nll::region_infer::values::RegionValueElements;
6+
use crate::dataflow::generic::ResultsCursor;
67
use crate::dataflow::indexes::BorrowIndex;
78
use crate::dataflow::move_paths::{InitLocation, MoveData, MovePathIndex, InitKind};
8-
use crate::dataflow::FlowAtLocation;
99
use crate::dataflow::MaybeInitializedPlaces;
1010
use crate::transform::MirSource;
1111
use crate::borrow_check::Upvar;
@@ -161,7 +161,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
161161
upvars: &[Upvar],
162162
location_table: &LocationTable,
163163
param_env: ty::ParamEnv<'tcx>,
164-
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'cx, 'tcx>>,
164+
flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'cx, 'tcx>>,
165165
move_data: &MoveData<'tcx>,
166166
borrow_set: &BorrowSet<'tcx>,
167167
errors_buffer: &mut Vec<Diagnostic>,

src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use crate::borrow_check::nll::facts::{AllFacts, AllFactsExt};
44
use crate::borrow_check::nll::region_infer::values::RegionValueElements;
55
use crate::borrow_check::nll::universal_regions::UniversalRegions;
66
use crate::borrow_check::nll::ToRegionVid;
7+
use crate::dataflow::generic::ResultsCursor;
78
use crate::dataflow::move_paths::MoveData;
8-
use crate::dataflow::FlowAtLocation;
99
use crate::dataflow::MaybeInitializedPlaces;
1010
use rustc::mir::{Body, Local};
1111
use rustc::ty::{RegionVid, TyCtxt};
@@ -26,11 +26,11 @@ mod trace;
2626
///
2727
/// N.B., this computation requires normalization; therefore, it must be
2828
/// performed before
29-
pub(super) fn generate<'tcx>(
29+
pub(super) fn generate<'mir, 'tcx>(
3030
typeck: &mut TypeChecker<'_, 'tcx>,
3131
body: &Body<'tcx>,
3232
elements: &Rc<RegionValueElements>,
33-
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>,
33+
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
3434
move_data: &MoveData<'tcx>,
3535
location_table: &LocationTable,
3636
) {

src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs

+22-18
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ use crate::borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap;
33
use crate::borrow_check::nll::type_check::liveness::polonius;
44
use crate::borrow_check::nll::type_check::NormalizeLocation;
55
use crate::borrow_check::nll::type_check::TypeChecker;
6+
use crate::dataflow::generic::ResultsCursor;
67
use crate::dataflow::indexes::MovePathIndex;
7-
use crate::dataflow::move_paths::MoveData;
8-
use crate::dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces};
8+
use crate::dataflow::move_paths::{HasMoveData, MoveData};
9+
use crate::dataflow::MaybeInitializedPlaces;
910
use rustc::infer::canonical::QueryRegionConstraints;
1011
use rustc::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
1112
use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
@@ -34,7 +35,7 @@ pub(super) fn trace(
3435
typeck: &mut TypeChecker<'_, 'tcx>,
3536
body: &Body<'tcx>,
3637
elements: &Rc<RegionValueElements>,
37-
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>,
38+
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
3839
move_data: &MoveData<'tcx>,
3940
live_locals: Vec<Local>,
4041
polonius_drop_used: Option<Vec<(Local, Location)>>,
@@ -81,7 +82,7 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> {
8182

8283
/// Results of dataflow tracking which variables (and paths) have been
8384
/// initialized.
84-
flow_inits: &'me mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'flow, 'tcx>>,
85+
flow_inits: &'me mut ResultsCursor<'flow, 'tcx, MaybeInitializedPlaces<'flow, 'tcx>>,
8586

8687
/// Index indicating where each variable is assigned, used, or
8788
/// dropped.
@@ -389,23 +390,26 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
389390
}
390391

391392
impl LivenessContext<'_, '_, '_, 'tcx> {
393+
/// Returns `true` if the local variable (or some part of it) is initialized at the current
394+
/// cursor position. Callers should call one of the `seek` methods immediately before to point
395+
/// the cursor to the desired location.
396+
fn initialized_at_curr_loc(&self, mpi: MovePathIndex) -> bool {
397+
let state = self.flow_inits.get();
398+
if state.contains(mpi) {
399+
return true;
400+
}
401+
402+
let move_paths = &self.flow_inits.analysis().move_data().move_paths;
403+
move_paths[mpi].find_child(&move_paths, |mpi| state.contains(mpi)).is_some()
404+
}
405+
392406
/// Returns `true` if the local variable (or some part of it) is initialized in
393407
/// the terminator of `block`. We need to check this to determine if a
394408
/// DROP of some local variable will have an effect -- note that
395409
/// drops, as they may unwind, are always terminators.
396410
fn initialized_at_terminator(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool {
397-
// Compute the set of initialized paths at terminator of block
398-
// by resetting to the start of the block and then applying
399-
// the effects of all statements. This is the only way to get
400-
// "just ahead" of a terminator.
401-
self.flow_inits.reset_to_entry_of(block);
402-
for statement_index in 0..self.body[block].statements.len() {
403-
let location = Location { block, statement_index };
404-
self.flow_inits.reconstruct_statement_effect(location);
405-
self.flow_inits.apply_local_effect(location);
406-
}
407-
408-
self.flow_inits.has_any_child_of(mpi).is_some()
411+
self.flow_inits.seek_before(self.body.terminator_loc(block));
412+
self.initialized_at_curr_loc(mpi)
409413
}
410414

411415
/// Returns `true` if the path `mpi` (or some part of it) is initialized at
@@ -414,8 +418,8 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
414418
/// **Warning:** Does not account for the result of `Call`
415419
/// instructions.
416420
fn initialized_at_exit(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool {
417-
self.flow_inits.reset_to_exit_of(block);
418-
self.flow_inits.has_any_child_of(mpi).is_some()
421+
self.flow_inits.seek_after(self.body.terminator_loc(block));
422+
self.initialized_at_curr_loc(mpi)
419423
}
420424

421425
/// Stores the result that all regions in `value` are live for the

src/librustc_mir/borrow_check/nll/type_check/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ use crate::borrow_check::nll::type_check::free_region_relations::{
1717
use crate::borrow_check::nll::universal_regions::{DefiningTy, UniversalRegions};
1818
use crate::borrow_check::nll::ToRegionVid;
1919
use crate::transform::promote_consts::should_suggest_const_in_array_repeat_expressions_attribute;
20+
use crate::dataflow::generic::ResultsCursor;
2021
use crate::dataflow::move_paths::MoveData;
21-
use crate::dataflow::FlowAtLocation;
2222
use crate::dataflow::MaybeInitializedPlaces;
2323
use either::Either;
2424
use rustc::hir;
@@ -112,7 +112,7 @@ mod relate_tys;
112112
/// constraints for the regions in the types of variables
113113
/// - `flow_inits` -- results of a maybe-init dataflow analysis
114114
/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
115-
pub(crate) fn type_check<'tcx>(
115+
pub(crate) fn type_check<'mir, 'tcx>(
116116
infcx: &InferCtxt<'_, 'tcx>,
117117
param_env: ty::ParamEnv<'tcx>,
118118
body: &Body<'tcx>,
@@ -122,7 +122,7 @@ pub(crate) fn type_check<'tcx>(
122122
location_table: &LocationTable,
123123
borrow_set: &BorrowSet<'tcx>,
124124
all_facts: &mut Option<AllFacts>,
125-
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>,
125+
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
126126
move_data: &MoveData<'tcx>,
127127
elements: &Rc<RegionValueElements>,
128128
) -> MirTypeckResults<'tcx> {

0 commit comments

Comments
 (0)