Auto merge of #118203 - nnethercote:rustc_mir_dataflow, r=cjgillot
Minor `rustc_mir_dataflow` cleanups r? `@cjgillot`
This commit is contained in:
commit
e2e978f713
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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,
|
||||||
|
@ -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());
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
|
@ -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};
|
||||||
|
@ -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| {
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
|
@ -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>,
|
||||||
|
@ -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>)> + '_ {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user