1
Fork 0

Remove ResultsVisitable.

Now that `Results` is the only impl of `ResultsVisitable`, the trait can
be removed. This simplifies things by removining unnecessary layers of
indirection and abstraction.

- `ResultsVisitor` is simpler.
  - Its type parameter changes from `R` (an analysis result) to the
    simpler `A` (an analysis).
  - It no longer needs the `Domain` associated type, because it can use
    `A::Domain`.
  - Occurrences of `R` become `Results<'tcx, A>`, because there is now
    only one kind of analysis results.

- `save_as_intervals` also changes type parameter from `R` to `A`.

- The `results.reconstruct_*` method calls are replaced with
  `results.analysis.apply_*` method calls, which are equivalent.

- `Direction::visit_results_in_block` is simpler, with a single generic
  param (`A`) instead of two (`D` and `R`/`F`, with a bound connecting
  them). Likewise for `visit_results`.

- The `ResultsVisitor` impls for `MirBorrowCtxt` and
  `StorageConflictVisitor` are now specific about the type of the
  analysis results they work with. They both used to have a type param
  `R` but they weren't genuinely generic. In both cases there was only a
  single results type that made sense to instantiate them with.
This commit is contained in:
Nicholas Nethercote 2024-10-31 12:33:12 +11:00
parent 3350edf8fd
commit c904c6aaff
10 changed files with 91 additions and 201 deletions

View file

@ -4,8 +4,8 @@ use rustc_middle::mir::{
self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges,
};
use super::visitor::{ResultsVisitable, ResultsVisitor};
use super::{Analysis, Effect, EffectIndex, SwitchIntTarget};
use super::visitor::ResultsVisitor;
use super::{Analysis, Effect, EffectIndex, Results, SwitchIntTarget};
pub trait Direction {
const IS_FORWARD: bool;
@ -33,14 +33,14 @@ pub trait Direction {
where
A: Analysis<'tcx>;
fn visit_results_in_block<'mir, 'tcx, D, R>(
state: &mut D,
fn visit_results_in_block<'mir, 'tcx, A>(
state: &mut A::Domain,
block: BasicBlock,
block_data: &'mir mir::BasicBlockData<'tcx>,
results: &mut R,
vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = D>,
results: &mut Results<'tcx, A>,
vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
) where
R: ResultsVisitable<'tcx, Domain = D>;
A: Analysis<'tcx>;
fn join_state_into_successors_of<'tcx, A>(
analysis: &mut A,
@ -53,7 +53,7 @@ pub trait Direction {
A: Analysis<'tcx>;
}
/// Dataflow that runs from the exit of a block (the terminator), to its entry (the first statement).
/// Dataflow that runs from the exit of a block (terminator), to its entry (the first statement).
pub struct Backward;
impl Direction for Backward {
@ -157,32 +157,32 @@ impl Direction for Backward {
analysis.apply_statement_effect(state, statement, location);
}
fn visit_results_in_block<'mir, 'tcx, D, R>(
state: &mut D,
fn visit_results_in_block<'mir, 'tcx, A>(
state: &mut A::Domain,
block: BasicBlock,
block_data: &'mir mir::BasicBlockData<'tcx>,
results: &mut R,
vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = D>,
results: &mut Results<'tcx, A>,
vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
) where
R: ResultsVisitable<'tcx, Domain = D>,
A: Analysis<'tcx>,
{
results.reset_to_block_entry(state, block);
state.clone_from(results.entry_set_for_block(block));
vis.visit_block_end(state);
// Terminator
let loc = Location { block, statement_index: block_data.statements.len() };
let term = block_data.terminator();
results.reconstruct_before_terminator_effect(state, term, loc);
results.analysis.apply_before_terminator_effect(state, term, loc);
vis.visit_terminator_before_primary_effect(results, state, term, loc);
results.reconstruct_terminator_effect(state, term, loc);
results.analysis.apply_terminator_effect(state, term, loc);
vis.visit_terminator_after_primary_effect(results, state, term, loc);
for (statement_index, stmt) in block_data.statements.iter().enumerate().rev() {
let loc = Location { block, statement_index };
results.reconstruct_before_statement_effect(state, stmt, loc);
results.analysis.apply_before_statement_effect(state, stmt, loc);
vis.visit_statement_before_primary_effect(results, state, stmt, loc);
results.reconstruct_statement_effect(state, stmt, loc);
results.analysis.apply_statement_effect(state, stmt, loc);
vis.visit_statement_after_primary_effect(results, state, stmt, loc);
}
@ -389,32 +389,32 @@ impl Direction for Forward {
}
}
fn visit_results_in_block<'mir, 'tcx, F, R>(
state: &mut F,
fn visit_results_in_block<'mir, 'tcx, A>(
state: &mut A::Domain,
block: BasicBlock,
block_data: &'mir mir::BasicBlockData<'tcx>,
results: &mut R,
vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = F>,
results: &mut Results<'tcx, A>,
vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
) where
R: ResultsVisitable<'tcx, Domain = F>,
A: Analysis<'tcx>,
{
results.reset_to_block_entry(state, block);
state.clone_from(results.entry_set_for_block(block));
vis.visit_block_start(state);
for (statement_index, stmt) in block_data.statements.iter().enumerate() {
let loc = Location { block, statement_index };
results.reconstruct_before_statement_effect(state, stmt, loc);
results.analysis.apply_before_statement_effect(state, stmt, loc);
vis.visit_statement_before_primary_effect(results, state, stmt, loc);
results.reconstruct_statement_effect(state, stmt, loc);
results.analysis.apply_statement_effect(state, stmt, loc);
vis.visit_statement_after_primary_effect(results, state, stmt, loc);
}
let loc = Location { block, statement_index: block_data.statements.len() };
let term = block_data.terminator();
results.reconstruct_before_terminator_effect(state, term, loc);
results.analysis.apply_before_terminator_effect(state, term, loc);
vis.visit_terminator_before_primary_effect(results, state, term, loc);
results.reconstruct_terminator_effect(state, term, loc);
results.analysis.apply_terminator_effect(state, term, loc);
vis.visit_terminator_after_primary_effect(results, state, term, loc);
vis.visit_block_end(state);

View file

@ -544,20 +544,18 @@ impl<D> StateDiffCollector<D> {
}
}
impl<'tcx, A> ResultsVisitor<'_, 'tcx, Results<'tcx, A>> for StateDiffCollector<A::Domain>
impl<'tcx, A> ResultsVisitor<'_, 'tcx, A> for StateDiffCollector<A::Domain>
where
A: Analysis<'tcx>,
A::Domain: DebugWithContext<A>,
{
type Domain = A::Domain;
fn visit_block_start(&mut self, state: &Self::Domain) {
fn visit_block_start(&mut self, state: &A::Domain) {
if A::Direction::IS_FORWARD {
self.prev_state.clone_from(state);
}
}
fn visit_block_end(&mut self, state: &Self::Domain) {
fn visit_block_end(&mut self, state: &A::Domain) {
if A::Direction::IS_BACKWARD {
self.prev_state.clone_from(state);
}
@ -566,7 +564,7 @@ where
fn visit_statement_before_primary_effect(
&mut self,
results: &mut Results<'tcx, A>,
state: &Self::Domain,
state: &A::Domain,
_statement: &mir::Statement<'tcx>,
_location: Location,
) {
@ -579,7 +577,7 @@ where
fn visit_statement_after_primary_effect(
&mut self,
results: &mut Results<'tcx, A>,
state: &Self::Domain,
state: &A::Domain,
_statement: &mir::Statement<'tcx>,
_location: Location,
) {
@ -590,7 +588,7 @@ where
fn visit_terminator_before_primary_effect(
&mut self,
results: &mut Results<'tcx, A>,
state: &Self::Domain,
state: &A::Domain,
_terminator: &mir::Terminator<'tcx>,
_location: Location,
) {
@ -603,7 +601,7 @@ where
fn visit_terminator_after_primary_effect(
&mut self,
results: &mut Results<'tcx, A>,
state: &Self::Domain,
state: &A::Domain,
_terminator: &mir::Terminator<'tcx>,
_location: Location,
) {

View file

@ -56,7 +56,7 @@ pub use self::cursor::ResultsCursor;
pub use self::direction::{Backward, Direction, Forward};
pub use self::lattice::{JoinSemiLattice, MaybeReachable};
pub use self::results::{EntrySets, Results};
pub use self::visitor::{ResultsVisitable, ResultsVisitor, visit_results};
pub use self::visitor::{ResultsVisitor, visit_results};
/// Analysis domains are all bitsets of various kinds. This trait holds
/// operations needed by all of them.

View file

@ -51,7 +51,7 @@ where
&mut self,
body: &'mir mir::Body<'tcx>,
blocks: impl IntoIterator<Item = BasicBlock>,
vis: &mut impl ResultsVisitor<'mir, 'tcx, Self, Domain = A::Domain>,
vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
) {
visit_results(body, blocks, self, vis)
}
@ -59,7 +59,7 @@ where
pub fn visit_reachable_with<'mir>(
&mut self,
body: &'mir mir::Body<'tcx>,
vis: &mut impl ResultsVisitor<'mir, 'tcx, Self, Domain = A::Domain>,
vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
) {
let blocks = traversal::reachable(body);
visit_results(body, blocks.map(|(bb, _)| bb), self, vis)

View file

@ -4,15 +4,15 @@ use super::{Analysis, Direction, Results};
/// Calls the corresponding method in `ResultsVisitor` for every location in a `mir::Body` with the
/// dataflow state at that location.
pub fn visit_results<'mir, 'tcx, D, R>(
pub fn visit_results<'mir, 'tcx, A>(
body: &'mir mir::Body<'tcx>,
blocks: impl IntoIterator<Item = BasicBlock>,
results: &mut R,
vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = D>,
results: &mut Results<'tcx, A>,
vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
) where
R: ResultsVisitable<'tcx, Domain = D>,
A: Analysis<'tcx>,
{
let mut state = results.bottom_value(body);
let mut state = results.analysis.bottom_value(body);
#[cfg(debug_assertions)]
let reachable_blocks = mir::traversal::reachable_as_bitset(body);
@ -22,23 +22,23 @@ pub fn visit_results<'mir, 'tcx, D, R>(
assert!(reachable_blocks.contains(block));
let block_data = &body[block];
R::Direction::visit_results_in_block(&mut state, block, block_data, results, vis);
A::Direction::visit_results_in_block(&mut state, block, block_data, results, vis);
}
}
/// A visitor over the results of an `Analysis`. The type parameter `R` is the results type being
/// visited.
pub trait ResultsVisitor<'mir, 'tcx, R> {
type Domain;
fn visit_block_start(&mut self, _state: &Self::Domain) {}
/// A visitor over the results of an `Analysis`.
pub trait ResultsVisitor<'mir, 'tcx, A>
where
A: Analysis<'tcx>,
{
fn visit_block_start(&mut self, _state: &A::Domain) {}
/// Called with the `before_statement_effect` of the given statement applied to `state` but not
/// its `statement_effect`.
fn visit_statement_before_primary_effect(
&mut self,
_results: &mut R,
_state: &Self::Domain,
_results: &mut Results<'tcx, A>,
_state: &A::Domain,
_statement: &'mir mir::Statement<'tcx>,
_location: Location,
) {
@ -48,19 +48,19 @@ pub trait ResultsVisitor<'mir, 'tcx, R> {
/// statement applied to `state`.
fn visit_statement_after_primary_effect(
&mut self,
_results: &mut R,
_state: &Self::Domain,
_results: &mut Results<'tcx, A>,
_state: &A::Domain,
_statement: &'mir mir::Statement<'tcx>,
_location: Location,
) {
}
/// Called with the `before_terminator_effect` of the given terminator applied to `state` but not
/// its `terminator_effect`.
/// Called with the `before_terminator_effect` of the given terminator applied to `state` but
/// not its `terminator_effect`.
fn visit_terminator_before_primary_effect(
&mut self,
_results: &mut R,
_state: &Self::Domain,
_results: &mut Results<'tcx, A>,
_state: &A::Domain,
_terminator: &'mir mir::Terminator<'tcx>,
_location: Location,
) {
@ -72,109 +72,12 @@ pub trait ResultsVisitor<'mir, 'tcx, R> {
/// The `call_return_effect` (if one exists) will *not* be applied to `state`.
fn visit_terminator_after_primary_effect(
&mut self,
_results: &mut R,
_state: &Self::Domain,
_results: &mut Results<'tcx, A>,
_state: &A::Domain,
_terminator: &'mir mir::Terminator<'tcx>,
_location: Location,
) {
}
fn visit_block_end(&mut self, _state: &Self::Domain) {}
}
/// Things that can be visited by a `ResultsVisitor`.
///
/// 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 Domain;
/// Creates an empty `Domain` to hold the transient state for these dataflow results.
///
/// The value of the newly created `Domain` will be overwritten by `reset_to_block_entry`
/// before it can be observed by a `ResultsVisitor`.
fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain;
fn reset_to_block_entry(&self, state: &mut Self::Domain, block: BasicBlock);
fn reconstruct_before_statement_effect(
&mut self,
state: &mut Self::Domain,
statement: &mir::Statement<'tcx>,
location: Location,
);
fn reconstruct_statement_effect(
&mut self,
state: &mut Self::Domain,
statement: &mir::Statement<'tcx>,
location: Location,
);
fn reconstruct_before_terminator_effect(
&mut self,
state: &mut Self::Domain,
terminator: &mir::Terminator<'tcx>,
location: Location,
);
fn reconstruct_terminator_effect(
&mut self,
state: &mut Self::Domain,
terminator: &mir::Terminator<'tcx>,
location: Location,
);
}
impl<'tcx, A> ResultsVisitable<'tcx> for Results<'tcx, A>
where
A: Analysis<'tcx>,
{
type Domain = A::Domain;
type Direction = A::Direction;
fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
self.analysis.bottom_value(body)
}
fn reset_to_block_entry(&self, state: &mut Self::Domain, block: BasicBlock) {
state.clone_from(self.entry_set_for_block(block));
}
fn reconstruct_before_statement_effect(
&mut self,
state: &mut Self::Domain,
stmt: &mir::Statement<'tcx>,
loc: Location,
) {
self.analysis.apply_before_statement_effect(state, stmt, loc);
}
fn reconstruct_statement_effect(
&mut self,
state: &mut Self::Domain,
stmt: &mir::Statement<'tcx>,
loc: Location,
) {
self.analysis.apply_statement_effect(state, stmt, loc);
}
fn reconstruct_before_terminator_effect(
&mut self,
state: &mut Self::Domain,
term: &mir::Terminator<'tcx>,
loc: Location,
) {
self.analysis.apply_before_terminator_effect(state, term, loc);
}
fn reconstruct_terminator_effect(
&mut self,
state: &mut Self::Domain,
term: &mir::Terminator<'tcx>,
loc: Location,
) {
self.analysis.apply_terminator_effect(state, term, loc);
}
fn visit_block_end(&mut self, _state: &A::Domain) {}
}