Rollup merge of #118638 - nnethercote:rustc_mir_dataflow-more, r=cjgillot
More `rustc_mir_dataflow` cleanups r? `@cjgillot`
This commit is contained in:
commit
546643c13c
@ -11,101 +11,88 @@ use rustc_middle::ty::TyCtxt;
|
||||
use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
|
||||
use rustc_mir_dataflow::ResultsVisitable;
|
||||
use rustc_mir_dataflow::{self, fmt::DebugWithContext, GenKill};
|
||||
use rustc_mir_dataflow::{Analysis, Direction, Results};
|
||||
use rustc_mir_dataflow::{Analysis, AnalysisDomain, Results};
|
||||
use std::fmt;
|
||||
|
||||
use crate::{places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext};
|
||||
|
||||
/// A tuple with named fields that can hold either the results or the transient state of the
|
||||
/// dataflow analyses used by the borrow checker.
|
||||
#[derive(Debug)]
|
||||
pub struct BorrowckAnalyses<B, U, E> {
|
||||
pub borrows: B,
|
||||
pub uninits: U,
|
||||
pub ever_inits: E,
|
||||
}
|
||||
|
||||
/// The results of the dataflow analyses used by the borrow checker.
|
||||
pub type BorrowckResults<'mir, 'tcx> = BorrowckAnalyses<
|
||||
Results<'tcx, Borrows<'mir, 'tcx>>,
|
||||
Results<'tcx, MaybeUninitializedPlaces<'mir, 'tcx>>,
|
||||
Results<'tcx, EverInitializedPlaces<'mir, 'tcx>>,
|
||||
>;
|
||||
pub struct BorrowckResults<'mir, 'tcx> {
|
||||
pub(crate) borrows: Results<'tcx, Borrows<'mir, 'tcx>>,
|
||||
pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'mir, 'tcx>>,
|
||||
pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'mir, 'tcx>>,
|
||||
}
|
||||
|
||||
/// The transient state of the dataflow analyses used by the borrow checker.
|
||||
pub type BorrowckFlowState<'mir, 'tcx> =
|
||||
<BorrowckResults<'mir, 'tcx> as ResultsVisitable<'tcx>>::FlowState;
|
||||
|
||||
macro_rules! impl_visitable {
|
||||
( $(
|
||||
$T:ident { $( $field:ident : $A:ident ),* $(,)? }
|
||||
)* ) => { $(
|
||||
impl<'tcx, $($A),*, D: Direction> ResultsVisitable<'tcx> for $T<$( Results<'tcx, $A> ),*>
|
||||
where
|
||||
$( $A: Analysis<'tcx, Direction = D>, )*
|
||||
{
|
||||
type Direction = D;
|
||||
type FlowState = $T<$( $A::Domain ),*>;
|
||||
|
||||
fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
|
||||
$T {
|
||||
$( $field: self.$field.analysis.bottom_value(body) ),*
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_to_block_entry(
|
||||
&self,
|
||||
state: &mut Self::FlowState,
|
||||
block: BasicBlock,
|
||||
) {
|
||||
$( state.$field.clone_from(&self.$field.entry_set_for_block(block)); )*
|
||||
}
|
||||
|
||||
fn reconstruct_before_statement_effect(
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
stmt: &mir::Statement<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
$( self.$field.analysis
|
||||
.apply_before_statement_effect(&mut state.$field, stmt, loc); )*
|
||||
}
|
||||
|
||||
fn reconstruct_statement_effect(
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
stmt: &mir::Statement<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
$( self.$field.analysis
|
||||
.apply_statement_effect(&mut state.$field, stmt, loc); )*
|
||||
}
|
||||
|
||||
fn reconstruct_before_terminator_effect(
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
term: &mir::Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
$( self.$field.analysis
|
||||
.apply_before_terminator_effect(&mut state.$field, term, loc); )*
|
||||
}
|
||||
|
||||
fn reconstruct_terminator_effect(
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
term: &mir::Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
$( self.$field.analysis
|
||||
.apply_terminator_effect(&mut state.$field, term, loc); )*
|
||||
}
|
||||
}
|
||||
)* }
|
||||
#[derive(Debug)]
|
||||
pub struct BorrowckFlowState<'mir, 'tcx> {
|
||||
pub(crate) borrows: <Borrows<'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
pub(crate) uninits: <MaybeUninitializedPlaces<'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
pub(crate) ever_inits: <EverInitializedPlaces<'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
}
|
||||
|
||||
impl_visitable! {
|
||||
BorrowckAnalyses { borrows: B, uninits: U, ever_inits: E }
|
||||
impl<'mir, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'mir, 'tcx> {
|
||||
// All three analyses are forward, but we have to use just one here.
|
||||
type Direction = <Borrows<'mir, 'tcx> as AnalysisDomain<'tcx>>::Direction;
|
||||
type FlowState = BorrowckFlowState<'mir, 'tcx>;
|
||||
|
||||
fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
|
||||
BorrowckFlowState {
|
||||
borrows: self.borrows.analysis.bottom_value(body),
|
||||
uninits: self.uninits.analysis.bottom_value(body),
|
||||
ever_inits: self.ever_inits.analysis.bottom_value(body),
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock) {
|
||||
state.borrows.clone_from(&self.borrows.entry_set_for_block(block));
|
||||
state.uninits.clone_from(&self.uninits.entry_set_for_block(block));
|
||||
state.ever_inits.clone_from(&self.ever_inits.entry_set_for_block(block));
|
||||
}
|
||||
|
||||
fn reconstruct_before_statement_effect(
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
stmt: &mir::Statement<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
self.borrows.analysis.apply_before_statement_effect(&mut state.borrows, stmt, loc);
|
||||
self.uninits.analysis.apply_before_statement_effect(&mut state.uninits, stmt, loc);
|
||||
self.ever_inits.analysis.apply_before_statement_effect(&mut state.ever_inits, stmt, loc);
|
||||
}
|
||||
|
||||
fn reconstruct_statement_effect(
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
stmt: &mir::Statement<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
self.borrows.analysis.apply_statement_effect(&mut state.borrows, stmt, loc);
|
||||
self.uninits.analysis.apply_statement_effect(&mut state.uninits, stmt, loc);
|
||||
self.ever_inits.analysis.apply_statement_effect(&mut state.ever_inits, stmt, loc);
|
||||
}
|
||||
|
||||
fn reconstruct_before_terminator_effect(
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
term: &mir::Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
self.borrows.analysis.apply_before_terminator_effect(&mut state.borrows, term, loc);
|
||||
self.uninits.analysis.apply_before_terminator_effect(&mut state.uninits, term, loc);
|
||||
self.ever_inits.analysis.apply_before_terminator_effect(&mut state.ever_inits, term, loc);
|
||||
}
|
||||
|
||||
fn reconstruct_terminator_effect(
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
term: &mir::Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
self.borrows.analysis.apply_terminator_effect(&mut state.borrows, term, loc);
|
||||
self.uninits.analysis.apply_terminator_effect(&mut state.uninits, term, loc);
|
||||
self.ever_inits.analysis.apply_terminator_effect(&mut state.ever_inits, term, loc);
|
||||
}
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
@ -598,7 +585,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
||||
|
||||
fn before_terminator_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
@ -625,7 +612,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
||||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_trans: &mut Self::Domain,
|
||||
_block: mir::BasicBlock,
|
||||
_return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
|
@ -196,7 +196,7 @@ impl Direction for Backward {
|
||||
{
|
||||
results.reset_to_block_entry(state, block);
|
||||
|
||||
vis.visit_block_end(results, state, block_data, block);
|
||||
vis.visit_block_end(state);
|
||||
|
||||
// Terminator
|
||||
let loc = Location { block, statement_index: block_data.statements.len() };
|
||||
@ -214,7 +214,7 @@ impl Direction for Backward {
|
||||
vis.visit_statement_after_primary_effect(results, state, stmt, loc);
|
||||
}
|
||||
|
||||
vis.visit_block_start(results, state, block_data, block);
|
||||
vis.visit_block_start(state);
|
||||
}
|
||||
|
||||
fn join_state_into_successors_of<'tcx, A>(
|
||||
@ -449,7 +449,7 @@ impl Direction for Forward {
|
||||
{
|
||||
results.reset_to_block_entry(state, block);
|
||||
|
||||
vis.visit_block_start(results, state, block_data, block);
|
||||
vis.visit_block_start(state);
|
||||
|
||||
for (statement_index, stmt) in block_data.statements.iter().enumerate() {
|
||||
let loc = Location { block, statement_index };
|
||||
@ -466,7 +466,7 @@ impl Direction for Forward {
|
||||
results.reconstruct_terminator_effect(state, term, loc);
|
||||
vis.visit_terminator_after_primary_effect(results, state, term, loc);
|
||||
|
||||
vis.visit_block_end(results, state, block_data, block);
|
||||
vis.visit_block_end(state);
|
||||
}
|
||||
|
||||
fn join_state_into_successors_of<'tcx, A>(
|
||||
|
@ -545,25 +545,13 @@ where
|
||||
{
|
||||
type FlowState = A::Domain;
|
||||
|
||||
fn visit_block_start(
|
||||
&mut self,
|
||||
_results: &mut Results<'tcx, A>,
|
||||
state: &Self::FlowState,
|
||||
_block_data: &mir::BasicBlockData<'tcx>,
|
||||
_block: BasicBlock,
|
||||
) {
|
||||
fn visit_block_start(&mut self, state: &Self::FlowState) {
|
||||
if A::Direction::IS_FORWARD {
|
||||
self.prev_state.clone_from(state);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_block_end(
|
||||
&mut self,
|
||||
_results: &mut Results<'tcx, A>,
|
||||
state: &Self::FlowState,
|
||||
_block_data: &mir::BasicBlockData<'tcx>,
|
||||
_block: BasicBlock,
|
||||
) {
|
||||
fn visit_block_end(&mut self, state: &Self::FlowState) {
|
||||
if A::Direction::IS_BACKWARD {
|
||||
self.prev_state.clone_from(state);
|
||||
}
|
||||
|
@ -248,18 +248,19 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
|
||||
|
||||
/// A gen/kill dataflow problem.
|
||||
///
|
||||
/// Each method in this trait has a corresponding one in `Analysis`. However, these methods only
|
||||
/// allow modification of the dataflow state via "gen" and "kill" operations. By defining transfer
|
||||
/// functions for each statement in this way, the transfer function for an entire basic block can
|
||||
/// be computed efficiently.
|
||||
/// Each method in this trait has a corresponding one in `Analysis`. However, the first two methods
|
||||
/// here only allow modification of the dataflow state via "gen" and "kill" operations. By defining
|
||||
/// transfer functions for each statement in this way, the transfer function for an entire basic
|
||||
/// block can be computed efficiently. The remaining methods match up with `Analysis` exactly.
|
||||
///
|
||||
/// `Analysis` is automatically implemented for all implementers of `GenKillAnalysis`.
|
||||
/// `Analysis` is automatically implemented for all implementers of `GenKillAnalysis` via a blanket
|
||||
/// impl below.
|
||||
pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
|
||||
type Idx: Idx;
|
||||
|
||||
fn domain_size(&self, body: &mir::Body<'tcx>) -> usize;
|
||||
|
||||
/// See `Analysis::apply_statement_effect`.
|
||||
/// See `Analysis::apply_statement_effect`. Note how the second arg differs.
|
||||
fn statement_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
@ -267,7 +268,8 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
|
||||
location: Location,
|
||||
);
|
||||
|
||||
/// See `Analysis::apply_before_statement_effect`.
|
||||
/// See `Analysis::apply_before_statement_effect`. Note how the second arg
|
||||
/// differs.
|
||||
fn before_statement_effect(
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
@ -287,7 +289,7 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
|
||||
/// See `Analysis::apply_before_terminator_effect`.
|
||||
fn before_terminator_effect(
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_trans: &mut Self::Domain,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
_location: Location,
|
||||
) {
|
||||
@ -298,7 +300,7 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
|
||||
/// See `Analysis::apply_call_return_effect`.
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
block: BasicBlock,
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
);
|
||||
@ -313,6 +315,7 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
// Blanket impl: any impl of `GenKillAnalysis` automatically impls `Analysis`.
|
||||
impl<'tcx, A> Analysis<'tcx> for A
|
||||
where
|
||||
A: GenKillAnalysis<'tcx>,
|
||||
|
@ -31,14 +31,7 @@ pub fn visit_results<'mir, 'tcx, F, R>(
|
||||
pub trait ResultsVisitor<'mir, 'tcx, R> {
|
||||
type FlowState;
|
||||
|
||||
fn visit_block_start(
|
||||
&mut self,
|
||||
_results: &mut R,
|
||||
_state: &Self::FlowState,
|
||||
_block_data: &'mir mir::BasicBlockData<'tcx>,
|
||||
_block: BasicBlock,
|
||||
) {
|
||||
}
|
||||
fn visit_block_start(&mut self, _state: &Self::FlowState) {}
|
||||
|
||||
/// Called with the `before_statement_effect` of the given statement applied to `state` but not
|
||||
/// its `statement_effect`.
|
||||
@ -86,20 +79,13 @@ pub trait ResultsVisitor<'mir, 'tcx, R> {
|
||||
) {
|
||||
}
|
||||
|
||||
fn visit_block_end(
|
||||
&mut self,
|
||||
_results: &mut R,
|
||||
_state: &Self::FlowState,
|
||||
_block_data: &'mir mir::BasicBlockData<'tcx>,
|
||||
_block: BasicBlock,
|
||||
) {
|
||||
}
|
||||
fn visit_block_end(&mut self, _state: &Self::FlowState) {}
|
||||
}
|
||||
|
||||
/// Things that can be visited by a `ResultsVisitor`.
|
||||
///
|
||||
/// This trait exists so that we can visit the results of multiple dataflow analyses simultaneously.
|
||||
/// DO NOT IMPLEMENT MANUALLY. Instead, use the `impl_visitable` macro below.
|
||||
/// This trait exists so that we can visit the results of one or more dataflow analyses
|
||||
/// simultaneously.
|
||||
pub trait ResultsVisitable<'tcx> {
|
||||
type Direction: Direction;
|
||||
type FlowState;
|
||||
|
@ -62,7 +62,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeBorrowedLocals {
|
||||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_trans: &mut Self::Domain,
|
||||
_block: BasicBlock,
|
||||
_return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
|
@ -376,7 +376,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
||||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
_block: mir::BasicBlock,
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
@ -499,7 +499,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
|
||||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
_block: mir::BasicBlock,
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
@ -617,7 +617,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> {
|
||||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
_block: mir::BasicBlock,
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
@ -712,7 +712,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
|
||||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
block: mir::BasicBlock,
|
||||
_return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
|
@ -69,7 +69,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeLiveLocals {
|
||||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
_block: mir::BasicBlock,
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
|
@ -72,7 +72,7 @@ impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> {
|
||||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_trans: &mut Self::Domain,
|
||||
_block: BasicBlock,
|
||||
_return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
@ -144,7 +144,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead {
|
||||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_trans: &mut Self::Domain,
|
||||
_block: BasicBlock,
|
||||
_return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
@ -238,7 +238,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
|
||||
|
||||
fn before_terminator_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
terminator: &Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
@ -334,7 +334,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
|
||||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
_block: BasicBlock,
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user