Skip to content

Commit 5c014ac

Browse files
committed
Auto merge of #65672 - ecstatic-morse:unified-dataflow-proto, r=<try>
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 8960acf + a9d46c7 commit 5c014ac

File tree

23 files changed

+1951
-826
lines changed

23 files changed

+1951
-826
lines changed

src/librustc/mir/mod.rs

+24
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,30 @@ impl<'tcx> Body<'tcx> {
194194
}
195195
}
196196

197+
/// Returns a partially initialized MIR body containing only a list of basic blocks.
198+
///
199+
/// The returned MIR contains no `LocalDecl`s (even for the return place) or source scopes. It
200+
/// is only useful for testing but cannot be `#[cfg(test)]` because it is used in a different
201+
/// crate.
202+
pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
203+
Body {
204+
phase: MirPhase::Build,
205+
basic_blocks,
206+
source_scopes: IndexVec::new(),
207+
yield_ty: None,
208+
generator_drop: None,
209+
generator_layout: None,
210+
local_decls: IndexVec::new(),
211+
user_type_annotations: IndexVec::new(),
212+
arg_count: 0,
213+
spread_arg: None,
214+
span: syntax_pos::DUMMY_SP,
215+
control_flow_destroyed: Vec::new(),
216+
generator_kind: None,
217+
var_debug_info: Vec::new(),
218+
}
219+
}
220+
197221
#[inline]
198222
pub fn basic_blocks(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
199223
&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

@@ -184,16 +184,10 @@ fn do_mir_borrowck<'a, 'tcx>(
184184
param_env,
185185
};
186186

187-
let dead_unwinds = BitSet::new_empty(body.basic_blocks().len());
188-
let mut flow_inits = FlowAtLocation::new(do_dataflow(
189-
tcx,
190-
&body,
191-
def_id,
192-
&attributes,
193-
&dead_unwinds,
194-
MaybeInitializedPlaces::new(tcx, &body, &mdpe),
195-
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
196-
));
187+
let flow_inits = MaybeInitializedPlaces::new(tcx, &body, &mdpe);
188+
let mut flow_inits = dataflow::generic::Engine::new_gen_kill(tcx, &body, def_id, flow_inits)
189+
.iterate_to_fixpoint()
190+
.into_cursor(&body);
197191

198192
let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(id).is_fn_or_closure();
199193
let borrow_set = Rc::new(BorrowSet::build(
@@ -223,6 +217,7 @@ fn do_mir_borrowck<'a, 'tcx>(
223217

224218
let regioncx = Rc::new(regioncx);
225219

220+
let dead_unwinds = BitSet::new_empty(body.basic_blocks().len());
226221
let flow_borrows = FlowAtLocation::new(do_dataflow(
227222
tcx,
228223
&body,

src/librustc_mir/borrow_check/nll/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use crate::borrow_check::location::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::move_paths::{InitLocation, MoveData, InitKind};
7-
use crate::dataflow::FlowAtLocation;
88
use crate::dataflow::MaybeInitializedPlaces;
99
use crate::transform::MirSource;
1010
use crate::borrow_check::Upvar;
@@ -165,7 +165,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
165165
upvars: &[Upvar],
166166
location_table: &LocationTable,
167167
param_env: ty::ParamEnv<'tcx>,
168-
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'cx, 'tcx>>,
168+
flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'cx, 'tcx>>,
169169
move_data: &MoveData<'tcx>,
170170
borrow_set: &BorrowSet<'tcx>,
171171
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, ReadOnlyBodyAndCache};
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: ReadOnlyBodyAndCache<'_, '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, ConstraintCategory, Local, Location, ReadOnlyBodyAndCache};
1112
use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
@@ -34,7 +35,7 @@ pub(super) fn trace(
3435
typeck: &mut TypeChecker<'_, 'tcx>,
3536
body: ReadOnlyBodyAndCache<'_, '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.
@@ -390,23 +391,26 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
390391
}
391392

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

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

422426
/// 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
@@ -50,7 +50,7 @@ use crate::borrow_check::nll::type_check::free_region_relations::{
5050
CreateResult, UniversalRegionRelations,
5151
};
5252
use crate::borrow_check::nll::universal_regions::{DefiningTy, UniversalRegions};
53-
use crate::dataflow::FlowAtLocation;
53+
use crate::dataflow::generic::ResultsCursor;
5454
use crate::dataflow::MaybeInitializedPlaces;
5555
use crate::dataflow::move_paths::MoveData;
5656
use crate::transform::promote_consts::should_suggest_const_in_array_repeat_expressions_attribute;
@@ -114,7 +114,7 @@ mod relate_tys;
114114
/// constraints for the regions in the types of variables
115115
/// - `flow_inits` -- results of a maybe-init dataflow analysis
116116
/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
117-
pub(crate) fn type_check<'tcx>(
117+
pub(crate) fn type_check<'mir, 'tcx>(
118118
infcx: &InferCtxt<'_, 'tcx>,
119119
param_env: ty::ParamEnv<'tcx>,
120120
body: ReadOnlyBodyAndCache<'_, 'tcx>,
@@ -124,7 +124,7 @@ pub(crate) fn type_check<'tcx>(
124124
location_table: &LocationTable,
125125
borrow_set: &BorrowSet<'tcx>,
126126
all_facts: &mut Option<AllFacts>,
127-
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>,
127+
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
128128
move_data: &MoveData<'tcx>,
129129
elements: &Rc<RegionValueElements>,
130130
) -> MirTypeckResults<'tcx> {

0 commit comments

Comments
 (0)