Auto merge of #118203 - nnethercote:rustc_mir_dataflow, r=cjgillot

Minor `rustc_mir_dataflow` cleanups

r? `@cjgillot`
This commit is contained in:
bors 2023-11-25 07:10:46 +00:00
commit e2e978f713
16 changed files with 132 additions and 227 deletions

View File

@ -121,24 +121,24 @@ pub struct BorrowIndex {}
/// `BorrowIndex`, and maps each such index to a `BorrowData` /// `BorrowIndex`, and maps each such index to a `BorrowData`
/// describing the borrow. These indexes are used for representing the /// describing the borrow. These indexes are used for representing the
/// borrows in compact bitvectors. /// borrows in compact bitvectors.
pub struct Borrows<'a, 'tcx> { pub struct Borrows<'mir, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>, body: &'mir Body<'tcx>,
borrow_set: &'a BorrowSet<'tcx>, borrow_set: &'mir BorrowSet<'tcx>,
borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>, borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
} }
struct OutOfScopePrecomputer<'a, 'tcx> { struct OutOfScopePrecomputer<'mir, 'tcx> {
visited: BitSet<mir::BasicBlock>, visited: BitSet<mir::BasicBlock>,
visit_stack: Vec<mir::BasicBlock>, visit_stack: Vec<mir::BasicBlock>,
body: &'a Body<'tcx>, body: &'mir Body<'tcx>,
regioncx: &'a RegionInferenceContext<'tcx>, regioncx: &'mir RegionInferenceContext<'tcx>,
borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>, borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
} }
impl<'a, 'tcx> OutOfScopePrecomputer<'a, 'tcx> { impl<'mir, 'tcx> OutOfScopePrecomputer<'mir, 'tcx> {
fn new(body: &'a Body<'tcx>, regioncx: &'a RegionInferenceContext<'tcx>) -> Self { fn new(body: &'mir Body<'tcx>, regioncx: &'mir RegionInferenceContext<'tcx>) -> Self {
OutOfScopePrecomputer { OutOfScopePrecomputer {
visited: BitSet::new_empty(body.basic_blocks.len()), visited: BitSet::new_empty(body.basic_blocks.len()),
visit_stack: vec![], visit_stack: vec![],
@ -241,17 +241,17 @@ pub fn calculate_borrows_out_of_scope_at_location<'tcx>(
prec.borrows_out_of_scope_at_location prec.borrows_out_of_scope_at_location
} }
struct PoloniusOutOfScopePrecomputer<'a, 'tcx> { struct PoloniusOutOfScopePrecomputer<'mir, 'tcx> {
visited: BitSet<mir::BasicBlock>, visited: BitSet<mir::BasicBlock>,
visit_stack: Vec<mir::BasicBlock>, visit_stack: Vec<mir::BasicBlock>,
body: &'a Body<'tcx>, body: &'mir Body<'tcx>,
regioncx: &'a RegionInferenceContext<'tcx>, regioncx: &'mir RegionInferenceContext<'tcx>,
loans_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>, loans_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
} }
impl<'a, 'tcx> PoloniusOutOfScopePrecomputer<'a, 'tcx> { impl<'mir, 'tcx> PoloniusOutOfScopePrecomputer<'mir, 'tcx> {
fn new(body: &'a Body<'tcx>, regioncx: &'a RegionInferenceContext<'tcx>) -> Self { fn new(body: &'mir Body<'tcx>, regioncx: &'mir RegionInferenceContext<'tcx>) -> Self {
Self { Self {
visited: BitSet::new_empty(body.basic_blocks.len()), visited: BitSet::new_empty(body.basic_blocks.len()),
visit_stack: vec![], visit_stack: vec![],
@ -404,12 +404,12 @@ fn loan_kill_location(
} }
} }
impl<'a, 'tcx> Borrows<'a, 'tcx> { impl<'mir, 'tcx> Borrows<'mir, 'tcx> {
pub fn new( pub fn new(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>, body: &'mir Body<'tcx>,
regioncx: &'a RegionInferenceContext<'tcx>, regioncx: &'mir RegionInferenceContext<'tcx>,
borrow_set: &'a BorrowSet<'tcx>, borrow_set: &'mir BorrowSet<'tcx>,
) -> Self { ) -> Self {
let mut borrows_out_of_scope_at_location = let mut borrows_out_of_scope_at_location =
calculate_borrows_out_of_scope_at_location(body, regioncx, borrow_set); calculate_borrows_out_of_scope_at_location(body, regioncx, borrow_set);

View File

@ -288,7 +288,7 @@ fn do_mir_borrowck<'tcx>(
.into_engine(tcx, body) .into_engine(tcx, body)
.pass_name("borrowck") .pass_name("borrowck")
.iterate_to_fixpoint(); .iterate_to_fixpoint();
let flow_ever_inits = EverInitializedPlaces::new(tcx, body, &mdpe) let flow_ever_inits = EverInitializedPlaces::new(body, &mdpe)
.into_engine(tcx, body) .into_engine(tcx, body)
.pass_name("borrowck") .pass_name("borrowck")
.iterate_to_fixpoint(); .iterate_to_fixpoint();

View File

@ -1,10 +1,8 @@
use crate::elaborate_drops::DropFlagState; use crate::elaborate_drops::DropFlagState;
use rustc_middle::mir::{self, Body, Location, Terminator, TerminatorKind}; use rustc_middle::mir::{self, Body, Location, Terminator, TerminatorKind};
use rustc_middle::ty::TyCtxt;
use rustc_target::abi::VariantIdx; use rustc_target::abi::VariantIdx;
use super::indexes::MovePathIndex; use super::move_paths::{InitKind, LookupResult, MoveData, MovePathIndex};
use super::move_paths::{InitKind, LookupResult, MoveData};
use super::MoveDataParamEnv; use super::MoveDataParamEnv;
pub fn move_path_children_matching<'tcx, F>( pub fn move_path_children_matching<'tcx, F>(
@ -30,8 +28,6 @@ pub fn move_path_children_matching<'tcx, F>(
} }
pub fn on_lookup_result_bits<'tcx, F>( pub fn on_lookup_result_bits<'tcx, F>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
lookup_result: LookupResult, lookup_result: LookupResult,
each_child: F, each_child: F,
@ -42,13 +38,11 @@ pub fn on_lookup_result_bits<'tcx, F>(
LookupResult::Parent(..) => { LookupResult::Parent(..) => {
// access to untracked value - do not touch children // access to untracked value - do not touch children
} }
LookupResult::Exact(e) => on_all_children_bits(tcx, body, move_data, e, each_child), LookupResult::Exact(e) => on_all_children_bits(move_data, e, each_child),
} }
} }
pub fn on_all_children_bits<'tcx, F>( pub fn on_all_children_bits<'tcx, F>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
move_path_index: MovePathIndex, move_path_index: MovePathIndex,
mut each_child: F, mut each_child: F,
@ -56,8 +50,6 @@ pub fn on_all_children_bits<'tcx, F>(
F: FnMut(MovePathIndex), F: FnMut(MovePathIndex),
{ {
fn on_all_children_bits<'tcx, F>( fn on_all_children_bits<'tcx, F>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
move_path_index: MovePathIndex, move_path_index: MovePathIndex,
each_child: &mut F, each_child: &mut F,
@ -68,15 +60,14 @@ fn on_all_children_bits<'tcx, F>(
let mut next_child_index = move_data.move_paths[move_path_index].first_child; let mut next_child_index = move_data.move_paths[move_path_index].first_child;
while let Some(child_index) = next_child_index { while let Some(child_index) = next_child_index {
on_all_children_bits(tcx, body, move_data, child_index, each_child); on_all_children_bits(move_data, child_index, each_child);
next_child_index = move_data.move_paths[child_index].next_sibling; next_child_index = move_data.move_paths[child_index].next_sibling;
} }
} }
on_all_children_bits(tcx, body, move_data, move_path_index, &mut each_child); on_all_children_bits(move_data, move_path_index, &mut each_child);
} }
pub fn drop_flag_effects_for_function_entry<'tcx, F>( pub fn drop_flag_effects_for_function_entry<'tcx, F>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
ctxt: &MoveDataParamEnv<'tcx>, ctxt: &MoveDataParamEnv<'tcx>,
mut callback: F, mut callback: F,
@ -87,14 +78,13 @@ pub fn drop_flag_effects_for_function_entry<'tcx, F>(
for arg in body.args_iter() { for arg in body.args_iter() {
let place = mir::Place::from(arg); let place = mir::Place::from(arg);
let lookup_result = move_data.rev_lookup.find(place.as_ref()); let lookup_result = move_data.rev_lookup.find(place.as_ref());
on_lookup_result_bits(tcx, body, move_data, lookup_result, |mpi| { on_lookup_result_bits(move_data, lookup_result, |mpi| {
callback(mpi, DropFlagState::Present) callback(mpi, DropFlagState::Present)
}); });
} }
} }
pub fn drop_flag_effects_for_location<'tcx, F>( pub fn drop_flag_effects_for_location<'tcx, F>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
ctxt: &MoveDataParamEnv<'tcx>, ctxt: &MoveDataParamEnv<'tcx>,
loc: Location, loc: Location,
@ -110,7 +100,7 @@ pub fn drop_flag_effects_for_location<'tcx, F>(
let path = mi.move_path_index(move_data); let path = mi.move_path_index(move_data);
debug!("moving out of path {:?}", move_data.move_paths[path]); debug!("moving out of path {:?}", move_data.move_paths[path]);
on_all_children_bits(tcx, body, move_data, path, |mpi| callback(mpi, DropFlagState::Absent)) on_all_children_bits(move_data, path, |mpi| callback(mpi, DropFlagState::Absent))
} }
// Drop does not count as a move but we should still consider the variable uninitialized. // Drop does not count as a move but we should still consider the variable uninitialized.
@ -118,24 +108,17 @@ pub fn drop_flag_effects_for_location<'tcx, F>(
body.stmt_at(loc).right() body.stmt_at(loc).right()
{ {
if let LookupResult::Exact(mpi) = move_data.rev_lookup.find(place.as_ref()) { if let LookupResult::Exact(mpi) = move_data.rev_lookup.find(place.as_ref()) {
on_all_children_bits(tcx, body, move_data, mpi, |mpi| { on_all_children_bits(move_data, mpi, |mpi| callback(mpi, DropFlagState::Absent))
callback(mpi, DropFlagState::Absent)
})
} }
} }
debug!("drop_flag_effects: assignment for location({:?})", loc); debug!("drop_flag_effects: assignment for location({:?})", loc);
for_location_inits(tcx, body, move_data, loc, |mpi| callback(mpi, DropFlagState::Present)); for_location_inits(move_data, loc, |mpi| callback(mpi, DropFlagState::Present));
} }
pub fn for_location_inits<'tcx, F>( fn for_location_inits<'tcx, F>(move_data: &MoveData<'tcx>, loc: Location, mut callback: F)
tcx: TyCtxt<'tcx>, where
body: &Body<'tcx>,
move_data: &MoveData<'tcx>,
loc: Location,
mut callback: F,
) where
F: FnMut(MovePathIndex), F: FnMut(MovePathIndex),
{ {
for ii in &move_data.init_loc_map[loc] { for ii in &move_data.init_loc_map[loc] {
@ -144,7 +127,7 @@ pub fn for_location_inits<'tcx, F>(
InitKind::Deep => { InitKind::Deep => {
let path = init.path; let path = init.path;
on_all_children_bits(tcx, body, move_data, path, &mut callback) on_all_children_bits(move_data, path, &mut callback)
} }
InitKind::Shallow => { InitKind::Shallow => {
let mpi = init.path; let mpi = init.path;
@ -161,8 +144,6 @@ pub fn for_location_inits<'tcx, F>(
/// NOTE: If there are no move paths corresponding to an inactive variant, /// NOTE: If there are no move paths corresponding to an inactive variant,
/// `handle_inactive_variant` will not be called for that variant. /// `handle_inactive_variant` will not be called for that variant.
pub(crate) fn on_all_inactive_variants<'tcx>( pub(crate) fn on_all_inactive_variants<'tcx>(
tcx: TyCtxt<'tcx>,
body: &mir::Body<'tcx>,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
enum_place: mir::Place<'tcx>, enum_place: mir::Place<'tcx>,
active_variant: VariantIdx, active_variant: VariantIdx,
@ -185,9 +166,7 @@ pub(crate) fn on_all_inactive_variants<'tcx>(
}; };
if variant_idx != active_variant { if variant_idx != active_variant {
on_all_children_bits(tcx, body, move_data, variant_mpi, |mpi| { on_all_children_bits(move_data, variant_mpi, |mpi| handle_inactive_variant(mpi));
handle_inactive_variant(mpi)
});
} }
} }
} }

View File

@ -147,7 +147,7 @@ pub(crate) fn allow_unreachable(&mut self) {
} }
/// Returns the underlying `Results`. /// Returns the underlying `Results`.
pub fn results(&mut self) -> &Results<'tcx, A, R::EntrySets> { pub fn results(&self) -> &Results<'tcx, A, R::EntrySets> {
self.results.borrow() self.results.borrow()
} }
@ -166,11 +166,6 @@ pub fn mut_analysis(&mut self) -> &mut A {
&mut self.results.borrow_mut().analysis &mut self.results.borrow_mut().analysis
} }
/// Returns both the dataflow state at the current location and the `Analysis`.
pub fn get_with_analysis(&mut self) -> (&A::Domain, &mut A) {
(&self.state, &mut self.results.borrow_mut().analysis)
}
/// Resets the cursor to hold the entry set for the given basic block. /// Resets the cursor to hold the entry set for the given basic block.
/// ///
/// For forward dataflow analyses, this is the dataflow state prior to the first statement. /// For forward dataflow analyses, this is the dataflow state prior to the first statement.

View File

@ -287,12 +287,12 @@ fn join_state_into_successors_of<'tcx, A>(
} }
} }
struct BackwardSwitchIntEdgeEffectsApplier<'a, 'tcx, D, F> { struct BackwardSwitchIntEdgeEffectsApplier<'mir, 'tcx, D, F> {
body: &'a mir::Body<'tcx>, body: &'mir mir::Body<'tcx>,
pred: BasicBlock, pred: BasicBlock,
exit_state: &'a mut D, exit_state: &'mir mut D,
bb: BasicBlock, bb: BasicBlock,
propagate: &'a mut F, propagate: &'mir mut F,
effects_applied: bool, effects_applied: bool,
} }
@ -523,9 +523,9 @@ fn join_state_into_successors_of<'tcx, A>(
} }
} }
struct ForwardSwitchIntEdgeEffectsApplier<'a, D, F> { struct ForwardSwitchIntEdgeEffectsApplier<'mir, D, F> {
exit_state: &'a mut D, exit_state: &'mir mut D,
targets: &'a SwitchTargets, targets: &'mir SwitchTargets,
propagate: F, propagate: F,
effects_applied: bool, effects_applied: bool,

View File

@ -128,12 +128,12 @@ pub fn reclone_analysis(&self) -> Self {
} }
/// A solver for dataflow problems. /// A solver for dataflow problems.
pub struct Engine<'a, 'tcx, A> pub struct Engine<'mir, 'tcx, A>
where where
A: Analysis<'tcx>, A: Analysis<'tcx>,
{ {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
body: &'a mir::Body<'tcx>, body: &'mir mir::Body<'tcx>,
entry_sets: IndexVec<BasicBlock, A::Domain>, entry_sets: IndexVec<BasicBlock, A::Domain>,
pass_name: Option<&'static str>, pass_name: Option<&'static str>,
analysis: A, analysis: A,
@ -147,14 +147,14 @@ pub struct Engine<'a, 'tcx, A>
apply_statement_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>, apply_statement_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>,
} }
impl<'a, 'tcx, A, D, T> Engine<'a, 'tcx, A> impl<'mir, 'tcx, A, D, T> Engine<'mir, 'tcx, A>
where where
A: GenKillAnalysis<'tcx, Idx = T, Domain = D>, A: GenKillAnalysis<'tcx, Idx = T, Domain = D>,
D: Clone + JoinSemiLattice + GenKill<T> + BitSetExt<T>, D: Clone + JoinSemiLattice + GenKill<T> + BitSetExt<T>,
T: Idx, T: Idx,
{ {
/// Creates a new `Engine` to solve a gen-kill dataflow problem. /// Creates a new `Engine` to solve a gen-kill dataflow problem.
pub fn new_gen_kill(tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>, mut analysis: A) -> Self { pub fn new_gen_kill(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, mut analysis: A) -> Self {
// If there are no back-edges in the control-flow graph, we only ever need to apply the // If there are no back-edges in the control-flow graph, we only ever need to apply the
// transfer function for each block exactly once (assuming that we process blocks in RPO). // transfer function for each block exactly once (assuming that we process blocks in RPO).
// //
@ -186,7 +186,7 @@ pub fn new_gen_kill(tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>, mut analysis:
} }
} }
impl<'a, 'tcx, A, D> Engine<'a, 'tcx, A> impl<'mir, 'tcx, A, D> Engine<'mir, 'tcx, A>
where where
A: Analysis<'tcx, Domain = D>, A: Analysis<'tcx, Domain = D>,
D: Clone + JoinSemiLattice, D: Clone + JoinSemiLattice,
@ -196,13 +196,13 @@ impl<'a, 'tcx, A, D> Engine<'a, 'tcx, A>
/// ///
/// Gen-kill problems should use `new_gen_kill`, which will coalesce transfer functions for /// Gen-kill problems should use `new_gen_kill`, which will coalesce transfer functions for
/// better performance. /// better performance.
pub fn new_generic(tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>, analysis: A) -> Self { pub fn new_generic(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, analysis: A) -> Self {
Self::new(tcx, body, analysis, None) Self::new(tcx, body, analysis, None)
} }
fn new( fn new(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
body: &'a mir::Body<'tcx>, body: &'mir mir::Body<'tcx>,
analysis: A, analysis: A,
apply_statement_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>, apply_statement_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>,
) -> Self { ) -> Self {
@ -239,7 +239,6 @@ pub fn iterate_to_fixpoint(self) -> Results<'tcx, A>
tcx, tcx,
apply_statement_trans_for_block, apply_statement_trans_for_block,
pass_name, pass_name,
..
} = self; } = self;
let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks.len()); let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks.len());

View File

@ -15,7 +15,7 @@
use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsRefCursor, ResultsVisitor}; use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsRefCursor, ResultsVisitor};
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum OutputStyle { pub(crate) enum OutputStyle {
AfterOnly, AfterOnly,
BeforeAndAfter, BeforeAndAfter,
} }
@ -29,7 +29,7 @@ fn num_state_columns(&self) -> usize {
} }
} }
pub struct Formatter<'res, 'mir, 'tcx, A> pub(crate) struct Formatter<'res, 'mir, 'tcx, A>
where where
A: Analysis<'tcx>, A: Analysis<'tcx>,
{ {
@ -43,7 +43,7 @@ impl<'res, 'mir, 'tcx, A> Formatter<'res, 'mir, 'tcx, A>
where where
A: Analysis<'tcx>, A: Analysis<'tcx>,
{ {
pub fn new( pub(crate) fn new(
body: &'mir Body<'tcx>, body: &'mir Body<'tcx>,
results: &'res mut Results<'tcx, A>, results: &'res mut Results<'tcx, A>,
style: OutputStyle, style: OutputStyle,
@ -55,7 +55,7 @@ pub fn new(
/// A pair of a basic block and an index into that basic blocks `successors`. /// A pair of a basic block and an index into that basic blocks `successors`.
#[derive(Copy, Clone, PartialEq, Eq, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct CfgEdge { pub(crate) struct CfgEdge {
source: BasicBlock, source: BasicBlock,
index: usize, index: usize,
} }

View File

@ -45,7 +45,7 @@
pub mod lattice; pub mod lattice;
mod visitor; mod visitor;
pub use self::cursor::{AnalysisResults, ResultsClonedCursor, ResultsCursor, ResultsRefCursor}; pub use self::cursor::{ResultsClonedCursor, ResultsCursor, ResultsRefCursor};
pub use self::direction::{Backward, Direction, Forward}; pub use self::direction::{Backward, Direction, Forward};
pub use self::engine::{Engine, EntrySets, Results, ResultsCloned}; pub use self::engine::{Engine, EntrySets, Results, ResultsCloned};
pub use self::lattice::{JoinSemiLattice, MaybeReachable}; pub use self::lattice::{JoinSemiLattice, MaybeReachable};

View File

@ -72,7 +72,7 @@ pub fn is_unwind_dead(
) -> bool { ) -> bool {
if let LookupResult::Exact(path) = self.move_data().rev_lookup.find(place.as_ref()) { if let LookupResult::Exact(path) = self.move_data().rev_lookup.find(place.as_ref()) {
let mut maybe_live = false; let mut maybe_live = false;
on_all_children_bits(self.tcx, self.body, self.move_data(), path, |child| { on_all_children_bits(self.move_data(), path, |child| {
maybe_live |= state.contains(child); maybe_live |= state.contains(child);
}); });
!maybe_live !maybe_live
@ -203,14 +203,13 @@ fn move_data(&self) -> &MoveData<'tcx> {
/// this data and `MaybeInitializedPlaces` yields the set of places /// this data and `MaybeInitializedPlaces` yields the set of places
/// that would require a dynamic drop-flag at that statement. /// that would require a dynamic drop-flag at that statement.
pub struct DefinitelyInitializedPlaces<'a, 'tcx> { pub struct DefinitelyInitializedPlaces<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>, body: &'a Body<'tcx>,
mdpe: &'a MoveDataParamEnv<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>,
} }
impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> { impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { pub fn new(body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
DefinitelyInitializedPlaces { tcx, body, mdpe } DefinitelyInitializedPlaces { body, mdpe }
} }
} }
@ -250,15 +249,13 @@ fn move_data(&self) -> &MoveData<'tcx> {
/// } /// }
/// ``` /// ```
pub struct EverInitializedPlaces<'a, 'tcx> { pub struct EverInitializedPlaces<'a, 'tcx> {
#[allow(dead_code)]
tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>, body: &'a Body<'tcx>,
mdpe: &'a MoveDataParamEnv<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>,
} }
impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> { impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { pub fn new(body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
EverInitializedPlaces { tcx, body, mdpe } EverInitializedPlaces { body, mdpe }
} }
} }
@ -319,7 +316,7 @@ fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) { fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
*state = *state =
MaybeReachable::Reachable(ChunkedBitSet::new_empty(self.move_data().move_paths.len())); MaybeReachable::Reachable(ChunkedBitSet::new_empty(self.move_data().move_paths.len()));
drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| { drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| {
assert!(s == DropFlagState::Present); assert!(s == DropFlagState::Present);
state.gen(path); state.gen(path);
}); });
@ -339,7 +336,7 @@ fn statement_effect(
statement: &mir::Statement<'tcx>, statement: &mir::Statement<'tcx>,
location: Location, location: Location,
) { ) {
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
Self::update_bits(trans, path, s) Self::update_bits(trans, path, s)
}); });
@ -351,7 +348,7 @@ fn statement_effect(
| mir::Rvalue::AddressOf(_, place) = rvalue | mir::Rvalue::AddressOf(_, place) = rvalue
&& let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) && let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref())
{ {
on_all_children_bits(self.tcx, self.body, self.move_data(), mpi, |child| { on_all_children_bits(self.move_data(), mpi, |child| {
trans.gen(child); trans.gen(child);
}) })
} }
@ -371,7 +368,7 @@ fn terminator_effect<'mir>(
{ {
edges = TerminatorEdges::Single(target); edges = TerminatorEdges::Single(target);
} }
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
Self::update_bits(state, path, s) Self::update_bits(state, path, s)
}); });
edges edges
@ -387,8 +384,6 @@ fn call_return_effect(
// when a call returns successfully, that means we need to set // when a call returns successfully, that means we need to set
// the bits for that dest_place to 1 (initialized). // the bits for that dest_place to 1 (initialized).
on_lookup_result_bits( on_lookup_result_bits(
self.tcx,
self.body,
self.move_data(), self.move_data(),
self.move_data().rev_lookup.find(place.as_ref()), self.move_data().rev_lookup.find(place.as_ref()),
|mpi| { |mpi| {
@ -432,8 +427,6 @@ fn switch_int_edge_effects<G: GenKill<Self::Idx>>(
// Kill all move paths that correspond to variants we know to be inactive along this // Kill all move paths that correspond to variants we know to be inactive along this
// particular outgoing edge of a `SwitchInt`. // particular outgoing edge of a `SwitchInt`.
drop_flag_effects::on_all_inactive_variants( drop_flag_effects::on_all_inactive_variants(
self.tcx,
self.body,
self.move_data(), self.move_data(),
enum_place, enum_place,
variant, variant,
@ -458,7 +451,7 @@ fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain)
// set all bits to 1 (uninit) before gathering counter-evidence // set all bits to 1 (uninit) before gathering counter-evidence
state.insert_all(); state.insert_all();
drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| { drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| {
assert!(s == DropFlagState::Present); assert!(s == DropFlagState::Present);
state.remove(path); state.remove(path);
}); });
@ -478,7 +471,7 @@ fn statement_effect(
_statement: &mir::Statement<'tcx>, _statement: &mir::Statement<'tcx>,
location: Location, location: Location,
) { ) {
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
Self::update_bits(trans, path, s) Self::update_bits(trans, path, s)
}); });
@ -492,7 +485,7 @@ fn terminator_effect<'mir>(
terminator: &'mir mir::Terminator<'tcx>, terminator: &'mir mir::Terminator<'tcx>,
location: Location, location: Location,
) -> TerminatorEdges<'mir, 'tcx> { ) -> TerminatorEdges<'mir, 'tcx> {
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
Self::update_bits(trans, path, s) Self::update_bits(trans, path, s)
}); });
if self.skip_unreachable_unwind.contains(location.block) { if self.skip_unreachable_unwind.contains(location.block) {
@ -514,8 +507,6 @@ fn call_return_effect(
// when a call returns successfully, that means we need to set // when a call returns successfully, that means we need to set
// the bits for that dest_place to 0 (initialized). // the bits for that dest_place to 0 (initialized).
on_lookup_result_bits( on_lookup_result_bits(
self.tcx,
self.body,
self.move_data(), self.move_data(),
self.move_data().rev_lookup.find(place.as_ref()), self.move_data().rev_lookup.find(place.as_ref()),
|mpi| { |mpi| {
@ -563,8 +554,6 @@ fn switch_int_edge_effects<G: GenKill<Self::Idx>>(
// Mark all move paths that correspond to variants other than this one as maybe // Mark all move paths that correspond to variants other than this one as maybe
// uninitialized (in reality, they are *definitely* uninitialized). // uninitialized (in reality, they are *definitely* uninitialized).
drop_flag_effects::on_all_inactive_variants( drop_flag_effects::on_all_inactive_variants(
self.tcx,
self.body,
self.move_data(), self.move_data(),
enum_place, enum_place,
variant, variant,
@ -589,7 +578,7 @@ fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) { fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
state.0.clear(); state.0.clear();
drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| { drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| {
assert!(s == DropFlagState::Present); assert!(s == DropFlagState::Present);
state.0.insert(path); state.0.insert(path);
}); });
@ -609,7 +598,7 @@ fn statement_effect(
_statement: &mir::Statement<'tcx>, _statement: &mir::Statement<'tcx>,
location: Location, location: Location,
) { ) {
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
Self::update_bits(trans, path, s) Self::update_bits(trans, path, s)
}) })
} }
@ -620,7 +609,7 @@ fn terminator_effect<'mir>(
terminator: &'mir mir::Terminator<'tcx>, terminator: &'mir mir::Terminator<'tcx>,
location: Location, location: Location,
) -> TerminatorEdges<'mir, 'tcx> { ) -> TerminatorEdges<'mir, 'tcx> {
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
Self::update_bits(trans, path, s) Self::update_bits(trans, path, s)
}); });
terminator.edges() terminator.edges()
@ -636,8 +625,6 @@ fn call_return_effect(
// when a call returns successfully, that means we need to set // when a call returns successfully, that means we need to set
// the bits for that dest_place to 1 (initialized). // the bits for that dest_place to 1 (initialized).
on_lookup_result_bits( on_lookup_result_bits(
self.tcx,
self.body,
self.move_data(), self.move_data(),
self.move_data().rev_lookup.find(place.as_ref()), self.move_data().rev_lookup.find(place.as_ref()),
|mpi| { |mpi| {

View File

@ -23,7 +23,6 @@
/// [`MaybeBorrowedLocals`]: super::MaybeBorrowedLocals /// [`MaybeBorrowedLocals`]: super::MaybeBorrowedLocals
/// [flow-test]: https://github.com/rust-lang/rust/blob/a08c47310c7d49cbdc5d7afb38408ba519967ecd/src/test/ui/mir-dataflow/liveness-ptr.rs /// [flow-test]: https://github.com/rust-lang/rust/blob/a08c47310c7d49cbdc5d7afb38408ba519967ecd/src/test/ui/mir-dataflow/liveness-ptr.rs
/// [liveness]: https://en.wikipedia.org/wiki/Live_variable_analysis /// [liveness]: https://en.wikipedia.org/wiki/Live_variable_analysis
#[derive(Clone, Copy)]
pub struct MaybeLiveLocals; pub struct MaybeLiveLocals;
impl<'tcx> AnalysisDomain<'tcx> for MaybeLiveLocals { impl<'tcx> AnalysisDomain<'tcx> for MaybeLiveLocals {

View File

@ -4,7 +4,6 @@
#![feature(let_chains)] #![feature(let_chains)]
#![feature(min_specialization)] #![feature(min_specialization)]
#![feature(stmt_expr_attributes)] #![feature(stmt_expr_attributes)]
#![feature(trusted_step)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
#![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)] #![deny(rustc::diagnostic_outside_of_impl)]
@ -14,24 +13,19 @@
#[macro_use] #[macro_use]
extern crate rustc_middle; extern crate rustc_middle;
use rustc_ast::MetaItem;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_fluent_macro::fluent_messages; use rustc_fluent_macro::fluent_messages;
use rustc_hir::def_id::DefId; use rustc_middle::ty;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::symbol::{sym, Symbol};
pub use self::drop_flag_effects::{ pub use self::drop_flag_effects::{
drop_flag_effects_for_function_entry, drop_flag_effects_for_location, drop_flag_effects_for_function_entry, drop_flag_effects_for_location,
move_path_children_matching, on_all_children_bits, on_lookup_result_bits, move_path_children_matching, on_all_children_bits, on_lookup_result_bits,
}; };
pub use self::framework::{ pub use self::framework::{
fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, AnalysisResults, Backward, fmt, lattice, visit_results, Analysis, AnalysisDomain, Direction, GenKill, GenKillAnalysis,
CloneAnalysis, Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, JoinSemiLattice, MaybeReachable, Results, ResultsCursor, ResultsVisitable, ResultsVisitor,
MaybeReachable, Results, ResultsCloned, ResultsClonedCursor, ResultsCursor, ResultsRefCursor,
ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects,
}; };
use self::framework::{Backward, CloneAnalysis, ResultsClonedCursor, SwitchIntEdgeEffects};
use self::move_paths::MoveData; use self::move_paths::MoveData;
pub mod debuginfo; pub mod debuginfo;
@ -48,24 +42,7 @@
fluent_messages! { "../messages.ftl" } fluent_messages! { "../messages.ftl" }
pub(crate) mod indexes {
pub(crate) use super::move_paths::MovePathIndex;
}
pub struct MoveDataParamEnv<'tcx> { pub struct MoveDataParamEnv<'tcx> {
pub move_data: MoveData<'tcx>, pub move_data: MoveData<'tcx>,
pub param_env: ty::ParamEnv<'tcx>, pub param_env: ty::ParamEnv<'tcx>,
} }
pub fn has_rustc_mir_with(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Option<MetaItem> {
for attr in tcx.get_attrs(def_id, sym::rustc_mir) {
let items = attr.meta_item_list();
for item in items.iter().flat_map(|l| l.iter()) {
match item.meta_item() {
Some(mi) if mi.has_name(name) => return Some(mi.clone()),
_ => continue,
}
}
}
None
}

View File

@ -1,11 +1,3 @@
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_index::bit_set::ChunkedBitSet;
use rustc_middle::mir::MirPass;
use rustc_middle::mir::{self, Body, Local, Location};
use rustc_middle::ty::{self, Ty, TyCtxt};
use crate::errors::{ use crate::errors::{
PeekArgumentNotALocal, PeekArgumentUntracked, PeekBitNotSet, PeekMustBeNotTemporary, PeekArgumentNotALocal, PeekArgumentUntracked, PeekBitNotSet, PeekMustBeNotTemporary,
PeekMustBePlaceOrRefPlace, StopAfterDataFlowEndedCompilation, PeekMustBePlaceOrRefPlace, StopAfterDataFlowEndedCompilation,
@ -18,13 +10,33 @@
use crate::move_paths::{LookupResult, MovePathIndex}; use crate::move_paths::{LookupResult, MovePathIndex};
use crate::MoveDataParamEnv; use crate::MoveDataParamEnv;
use crate::{Analysis, JoinSemiLattice, ResultsCursor}; use crate::{Analysis, JoinSemiLattice, ResultsCursor};
use rustc_ast::MetaItem;
use rustc_hir::def_id::DefId;
use rustc_index::bit_set::ChunkedBitSet;
use rustc_middle::mir::MirPass;
use rustc_middle::mir::{self, Body, Local, Location};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
pub struct SanityCheck; pub struct SanityCheck;
fn has_rustc_mir_with(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Option<MetaItem> {
for attr in tcx.get_attrs(def_id, sym::rustc_mir) {
let items = attr.meta_item_list();
for item in items.iter().flat_map(|l| l.iter()) {
match item.meta_item() {
Some(mi) if mi.has_name(name) => return Some(mi.clone()),
_ => continue,
}
}
}
None
}
// FIXME: This should be a `MirLint`, but it needs to be moved back to `rustc_mir_transform` first. // FIXME: This should be a `MirLint`, but it needs to be moved back to `rustc_mir_transform` first.
impl<'tcx> MirPass<'tcx> for SanityCheck { impl<'tcx> MirPass<'tcx> for SanityCheck {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
use crate::has_rustc_mir_with;
let def_id = body.source.def_id(); let def_id = body.source.def_id();
if !tcx.has_attr(def_id, sym::rustc_mir) { if !tcx.has_attr(def_id, sym::rustc_mir) {
debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
@ -54,7 +66,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
} }
if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_definite_init).is_some() { if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_definite_init).is_some() {
let flow_def_inits = DefinitelyInitializedPlaces::new(tcx, body, &mdpe) let flow_def_inits = DefinitelyInitializedPlaces::new(body, &mdpe)
.into_engine(tcx, body) .into_engine(tcx, body)
.iterate_to_fixpoint(); .iterate_to_fixpoint();
@ -89,10 +101,8 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
/// (If there are any calls to `rustc_peek` that do not match the /// (If there are any calls to `rustc_peek` that do not match the
/// expression form above, then that emits an error as well, but those /// expression form above, then that emits an error as well, but those
/// errors are not intended to be used for unit tests.) /// errors are not intended to be used for unit tests.)
pub fn sanity_check_via_rustc_peek<'tcx, A>( fn sanity_check_via_rustc_peek<'tcx, A>(tcx: TyCtxt<'tcx>, mut cursor: ResultsCursor<'_, 'tcx, A>)
tcx: TyCtxt<'tcx>, where
mut cursor: ResultsCursor<'_, 'tcx, A>,
) where
A: RustcPeekAt<'tcx>, A: RustcPeekAt<'tcx>,
{ {
let def_id = cursor.body().source.def_id(); let def_id = cursor.body().source.def_id();
@ -129,7 +139,8 @@ pub fn sanity_check_via_rustc_peek<'tcx, A>(
) => { ) => {
let loc = Location { block: bb, statement_index }; let loc = Location { block: bb, statement_index };
cursor.seek_before_primary_effect(loc); cursor.seek_before_primary_effect(loc);
let (state, analysis) = cursor.get_with_analysis(); let state = cursor.get();
let analysis = cursor.analysis();
analysis.peek_at(tcx, *place, state, call); analysis.peek_at(tcx, *place, state, call);
} }
@ -173,7 +184,7 @@ fn from_arg_ty(arg: Ty<'_>) -> Self {
} }
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub struct PeekCall { struct PeekCall {
arg: Local, arg: Local,
kind: PeekCallKind, kind: PeekCallKind,
span: Span, span: Span,
@ -221,7 +232,7 @@ fn from_terminator<'tcx>(
} }
} }
pub trait RustcPeekAt<'tcx>: Analysis<'tcx> { trait RustcPeekAt<'tcx>: Analysis<'tcx> {
fn peek_at( fn peek_at(
&self, &self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,

View File

@ -3,13 +3,13 @@
/// Used for reverting changes made by `DerefSeparator` /// Used for reverting changes made by `DerefSeparator`
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct UnDerefer<'tcx> { pub(crate) struct UnDerefer<'tcx> {
deref_chains: FxHashMap<Local, Vec<PlaceRef<'tcx>>>, deref_chains: FxHashMap<Local, Vec<PlaceRef<'tcx>>>,
} }
impl<'tcx> UnDerefer<'tcx> { impl<'tcx> UnDerefer<'tcx> {
#[inline] #[inline]
pub fn insert(&mut self, local: Local, reffed: PlaceRef<'tcx>) { pub(crate) fn insert(&mut self, local: Local, reffed: PlaceRef<'tcx>) {
let mut chain = self.deref_chains.remove(&reffed.local).unwrap_or_default(); let mut chain = self.deref_chains.remove(&reffed.local).unwrap_or_default();
chain.push(reffed); chain.push(reffed);
self.deref_chains.insert(local, chain); self.deref_chains.insert(local, chain);
@ -17,7 +17,7 @@ pub fn insert(&mut self, local: Local, reffed: PlaceRef<'tcx>) {
/// Returns the chain of places behind `DerefTemp` locals /// Returns the chain of places behind `DerefTemp` locals
#[inline] #[inline]
pub fn deref_chain(&self, local: Local) -> &[PlaceRef<'tcx>] { pub(crate) fn deref_chain(&self, local: Local) -> &[PlaceRef<'tcx>] {
self.deref_chains.get(&local).map(Vec::as_slice).unwrap_or_default() self.deref_chains.get(&local).map(Vec::as_slice).unwrap_or_default()
} }
@ -25,7 +25,7 @@ pub fn deref_chain(&self, local: Local) -> &[PlaceRef<'tcx>] {
/// ///
/// See [`PlaceRef::iter_projections`] /// See [`PlaceRef::iter_projections`]
#[inline] #[inline]
pub fn iter_projections( pub(crate) fn iter_projections(
&self, &self,
place: PlaceRef<'tcx>, place: PlaceRef<'tcx>,
) -> impl Iterator<Item = (PlaceRef<'tcx>, PlaceElem<'tcx>)> + '_ { ) -> impl Iterator<Item = (PlaceRef<'tcx>, PlaceElem<'tcx>)> + '_ {

View File

@ -332,8 +332,6 @@ fn wrap(self) -> ValueAnalysisWrapper<Self>
impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper<T> { impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper<T> {
type Domain = State<T::Value>; type Domain = State<T::Value>;
type Direction = crate::Forward;
const NAME: &'static str = T::NAME; const NAME: &'static str = T::NAME;
fn bottom_value(&self, _body: &Body<'tcx>) -> Self::Domain { fn bottom_value(&self, _body: &Body<'tcx>) -> Self::Domain {
@ -476,26 +474,10 @@ pub fn all(&self, f: impl Fn(&V) -> bool) -> bool {
} }
} }
pub fn is_reachable(&self) -> bool { fn is_reachable(&self) -> bool {
matches!(&self.0, StateData::Reachable(_)) matches!(&self.0, StateData::Reachable(_))
} }
pub fn mark_unreachable(&mut self) {
self.0 = StateData::Unreachable;
}
pub fn flood_all(&mut self)
where
V: HasTop,
{
self.flood_all_with(V::TOP)
}
pub fn flood_all_with(&mut self, value: V) {
let StateData::Reachable(values) = &mut self.0 else { return };
values.raw.fill(value);
}
/// Assign `value` to all places that are contained in `place` or may alias one. /// Assign `value` to all places that are contained in `place` or may alias one.
pub fn flood_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) { pub fn flood_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) {
self.flood_with_tail_elem(place, None, map, value) self.flood_with_tail_elem(place, None, map, value)
@ -510,7 +492,7 @@ pub fn flood(&mut self, place: PlaceRef<'_>, map: &Map)
} }
/// Assign `value` to the discriminant of `place` and all places that may alias it. /// Assign `value` to the discriminant of `place` and all places that may alias it.
pub fn flood_discr_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) { fn flood_discr_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) {
self.flood_with_tail_elem(place, Some(TrackElem::Discriminant), map, value) self.flood_with_tail_elem(place, Some(TrackElem::Discriminant), map, value)
} }
@ -546,7 +528,7 @@ pub fn flood_with_tail_elem(
/// This does nothing if the place is not tracked. /// This does nothing if the place is not tracked.
/// ///
/// The target place must have been flooded before calling this method. /// The target place must have been flooded before calling this method.
pub fn insert_idx(&mut self, target: PlaceIndex, result: ValueOrPlace<V>, map: &Map) { fn insert_idx(&mut self, target: PlaceIndex, result: ValueOrPlace<V>, map: &Map) {
match result { match result {
ValueOrPlace::Value(value) => self.insert_value_idx(target, value, map), ValueOrPlace::Value(value) => self.insert_value_idx(target, value, map),
ValueOrPlace::Place(source) => self.insert_place_idx(target, source, map), ValueOrPlace::Place(source) => self.insert_place_idx(target, source, map),
@ -910,18 +892,13 @@ fn cache_preorder_invoke(&mut self, root: PlaceIndex) {
self.inner_values[root] = start..end; self.inner_values[root] = start..end;
} }
/// Returns the number of tracked places, i.e., those for which a value can be stored.
pub fn tracked_places(&self) -> usize {
self.value_count
}
/// Applies a single projection element, yielding the corresponding child. /// Applies a single projection element, yielding the corresponding child.
pub fn apply(&self, place: PlaceIndex, elem: TrackElem) -> Option<PlaceIndex> { pub fn apply(&self, place: PlaceIndex, elem: TrackElem) -> Option<PlaceIndex> {
self.projections.get(&(place, elem)).copied() self.projections.get(&(place, elem)).copied()
} }
/// Locates the given place, if it exists in the tree. /// Locates the given place, if it exists in the tree.
pub fn find_extra( fn find_extra(
&self, &self,
place: PlaceRef<'_>, place: PlaceRef<'_>,
extra: impl IntoIterator<Item = TrackElem>, extra: impl IntoIterator<Item = TrackElem>,
@ -954,7 +931,7 @@ pub fn find_len(&self, place: PlaceRef<'_>) -> Option<PlaceIndex> {
} }
/// Iterate over all direct children. /// Iterate over all direct children.
pub fn children(&self, parent: PlaceIndex) -> impl Iterator<Item = PlaceIndex> + '_ { fn children(&self, parent: PlaceIndex) -> impl Iterator<Item = PlaceIndex> + '_ {
Children::new(self, parent) Children::new(self, parent)
} }

View File

@ -667,36 +667,34 @@ fn locals_live_across_suspend_points<'tcx>(
always_live_locals: &BitSet<Local>, always_live_locals: &BitSet<Local>,
movable: bool, movable: bool,
) -> LivenessInfo { ) -> LivenessInfo {
let body_ref: &Body<'_> = body;
// Calculate when MIR locals have live storage. This gives us an upper bound of their // Calculate when MIR locals have live storage. This gives us an upper bound of their
// lifetimes. // lifetimes.
let mut storage_live = MaybeStorageLive::new(std::borrow::Cow::Borrowed(always_live_locals)) let mut storage_live = MaybeStorageLive::new(std::borrow::Cow::Borrowed(always_live_locals))
.into_engine(tcx, body_ref) .into_engine(tcx, body)
.iterate_to_fixpoint() .iterate_to_fixpoint()
.into_results_cursor(body_ref); .into_results_cursor(body);
// Calculate the MIR locals which have been previously // Calculate the MIR locals which have been previously
// borrowed (even if they are still active). // borrowed (even if they are still active).
let borrowed_locals_results = let borrowed_locals_results =
MaybeBorrowedLocals.into_engine(tcx, body_ref).pass_name("coroutine").iterate_to_fixpoint(); MaybeBorrowedLocals.into_engine(tcx, body).pass_name("coroutine").iterate_to_fixpoint();
let mut borrowed_locals_cursor = borrowed_locals_results.cloned_results_cursor(body_ref); let mut borrowed_locals_cursor = borrowed_locals_results.cloned_results_cursor(body);
// Calculate the MIR locals that we actually need to keep storage around // Calculate the MIR locals that we actually need to keep storage around
// for. // for.
let mut requires_storage_results = let mut requires_storage_results =
MaybeRequiresStorage::new(borrowed_locals_results.cloned_results_cursor(body)) MaybeRequiresStorage::new(borrowed_locals_results.cloned_results_cursor(body))
.into_engine(tcx, body_ref) .into_engine(tcx, body)
.iterate_to_fixpoint(); .iterate_to_fixpoint();
let mut requires_storage_cursor = requires_storage_results.as_results_cursor(body_ref); let mut requires_storage_cursor = requires_storage_results.as_results_cursor(body);
// Calculate the liveness of MIR locals ignoring borrows. // Calculate the liveness of MIR locals ignoring borrows.
let mut liveness = MaybeLiveLocals let mut liveness = MaybeLiveLocals
.into_engine(tcx, body_ref) .into_engine(tcx, body)
.pass_name("coroutine") .pass_name("coroutine")
.iterate_to_fixpoint() .iterate_to_fixpoint()
.into_results_cursor(body_ref); .into_results_cursor(body);
let mut storage_liveness_map = IndexVec::from_elem(None, &body.basic_blocks); let mut storage_liveness_map = IndexVec::from_elem(None, &body.basic_blocks);
let mut live_locals_at_suspension_points = Vec::new(); let mut live_locals_at_suspension_points = Vec::new();
@ -762,7 +760,7 @@ fn locals_live_across_suspend_points<'tcx>(
.collect(); .collect();
let storage_conflicts = compute_storage_conflicts( let storage_conflicts = compute_storage_conflicts(
body_ref, body,
&saved_locals, &saved_locals,
always_live_locals.clone(), always_live_locals.clone(),
requires_storage_results, requires_storage_results,

View File

@ -172,19 +172,13 @@ fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle {
let mut some_live = false; let mut some_live = false;
let mut some_dead = false; let mut some_dead = false;
let mut children_count = 0; let mut children_count = 0;
on_all_children_bits( on_all_children_bits(self.ctxt.move_data(), path, |child| {
self.tcx(), let (live, dead) = self.ctxt.init_data.maybe_live_dead(child);
self.body(), debug!("elaborate_drop: state({:?}) = {:?}", child, (live, dead));
self.ctxt.move_data(), some_live |= live;
path, some_dead |= dead;
|child| { children_count += 1;
let (live, dead) = self.ctxt.init_data.maybe_live_dead(child); });
debug!("elaborate_drop: state({:?}) = {:?}", child, (live, dead));
some_live |= live;
some_dead |= dead;
children_count += 1;
},
);
((some_live, some_dead), children_count != 1) ((some_live, some_dead), children_count != 1)
} }
}; };
@ -202,13 +196,9 @@ fn clear_drop_flag(&mut self, loc: Location, path: Self::Path, mode: DropFlagMod
self.ctxt.set_drop_flag(loc, path, DropFlagState::Absent); self.ctxt.set_drop_flag(loc, path, DropFlagState::Absent);
} }
DropFlagMode::Deep => { DropFlagMode::Deep => {
on_all_children_bits( on_all_children_bits(self.ctxt.move_data(), path, |child| {
self.tcx(), self.ctxt.set_drop_flag(loc, child, DropFlagState::Absent)
self.body(), });
self.ctxt.move_data(),
path,
|child| self.ctxt.set_drop_flag(loc, child, DropFlagState::Absent),
);
} }
} }
} }
@ -268,10 +258,9 @@ fn param_env(&self) -> ty::ParamEnv<'tcx> {
} }
fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) { fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) {
let tcx = self.tcx;
let patch = &mut self.patch; let patch = &mut self.patch;
debug!("create_drop_flag({:?})", self.body.span); debug!("create_drop_flag({:?})", self.body.span);
self.drop_flags[index].get_or_insert_with(|| patch.new_temp(tcx.types.bool, span)); self.drop_flags[index].get_or_insert_with(|| patch.new_temp(self.tcx.types.bool, span));
} }
fn drop_flag(&mut self, index: MovePathIndex) -> Option<Place<'tcx>> { fn drop_flag(&mut self, index: MovePathIndex) -> Option<Place<'tcx>> {
@ -304,7 +293,7 @@ fn collect_drop_flags(&mut self) {
match path { match path {
LookupResult::Exact(path) => { LookupResult::Exact(path) => {
self.init_data.seek_before(self.body.terminator_loc(bb)); self.init_data.seek_before(self.body.terminator_loc(bb));
on_all_children_bits(self.tcx, self.body, self.move_data(), path, |child| { on_all_children_bits(self.move_data(), path, |child| {
let (maybe_live, maybe_dead) = self.init_data.maybe_live_dead(child); let (maybe_live, maybe_dead) = self.init_data.maybe_live_dead(child);
debug!( debug!(
"collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}", "collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}",
@ -444,7 +433,7 @@ fn drop_flags_for_fn_rets(&mut self) {
let loc = Location { block: tgt, statement_index: 0 }; let loc = Location { block: tgt, statement_index: 0 };
let path = self.move_data().rev_lookup.find(destination.as_ref()); let path = self.move_data().rev_lookup.find(destination.as_ref());
on_lookup_result_bits(self.tcx, self.body, self.move_data(), path, |child| { on_lookup_result_bits(self.move_data(), path, |child| {
self.set_drop_flag(loc, child, DropFlagState::Present) self.set_drop_flag(loc, child, DropFlagState::Present)
}); });
} }
@ -453,14 +442,9 @@ fn drop_flags_for_fn_rets(&mut self) {
fn drop_flags_for_args(&mut self) { fn drop_flags_for_args(&mut self) {
let loc = Location::START; let loc = Location::START;
rustc_mir_dataflow::drop_flag_effects_for_function_entry( rustc_mir_dataflow::drop_flag_effects_for_function_entry(self.body, self.env, |path, ds| {
self.tcx, self.set_drop_flag(loc, path, ds);
self.body, })
self.env,
|path, ds| {
self.set_drop_flag(loc, path, ds);
},
)
} }
fn drop_flags_for_locs(&mut self) { fn drop_flags_for_locs(&mut self) {
@ -492,7 +476,6 @@ fn drop_flags_for_locs(&mut self) {
} }
let loc = Location { block: bb, statement_index: i }; let loc = Location { block: bb, statement_index: i };
rustc_mir_dataflow::drop_flag_effects_for_location( rustc_mir_dataflow::drop_flag_effects_for_location(
self.tcx,
self.body, self.body,
self.env, self.env,
loc, loc,
@ -515,7 +498,7 @@ fn drop_flags_for_locs(&mut self) {
let loc = Location { block: bb, statement_index: data.statements.len() }; let loc = Location { block: bb, statement_index: data.statements.len() };
let path = self.move_data().rev_lookup.find(destination.as_ref()); let path = self.move_data().rev_lookup.find(destination.as_ref());
on_lookup_result_bits(self.tcx, self.body, self.move_data(), path, |child| { on_lookup_result_bits(self.move_data(), path, |child| {
self.set_drop_flag(loc, child, DropFlagState::Present) self.set_drop_flag(loc, child, DropFlagState::Present)
}); });
} }