//! Dataflow analysis results. use rustc_index::IndexVec; use rustc_middle::mir::{BasicBlock, Body, traversal}; use super::{Analysis, ResultsCursor, ResultsVisitor, visit_results}; use crate::framework::cursor::ResultsHandle; pub type EntryStates<'tcx, A> = IndexVec>::Domain>; /// A dataflow analysis that has converged to fixpoint. It only holds the domain values at the /// entry of each basic block. Domain values in other parts of the block are recomputed on the fly /// by visitors (i.e. `ResultsCursor`, or `ResultsVisitor` impls). #[derive(Clone)] pub struct Results<'tcx, A> where A: Analysis<'tcx>, { pub analysis: A, pub entry_states: EntryStates<'tcx, A>, } impl<'tcx, A> Results<'tcx, A> where A: Analysis<'tcx>, { /// Creates a `ResultsCursor` that mutably borrows the `Results`, which is appropriate when the /// `Results` is also used outside the cursor. pub fn as_results_cursor<'mir>( &'mir mut self, body: &'mir Body<'tcx>, ) -> ResultsCursor<'mir, 'tcx, A> { ResultsCursor::new(body, ResultsHandle::BorrowedMut(self)) } /// Creates a `ResultsCursor` that takes ownership of the `Results`. pub fn into_results_cursor<'mir>(self, body: &'mir Body<'tcx>) -> ResultsCursor<'mir, 'tcx, A> { ResultsCursor::new(body, ResultsHandle::Owned(self)) } /// Gets the dataflow state for the given block. pub fn entry_set_for_block(&self, block: BasicBlock) -> &A::Domain { &self.entry_states[block] } pub fn visit_with<'mir>( &mut self, body: &'mir Body<'tcx>, blocks: impl IntoIterator, vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) { visit_results(body, blocks, self, vis) } pub fn visit_reachable_with<'mir>( &mut self, body: &'mir Body<'tcx>, vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) { let blocks = traversal::reachable(body); visit_results(body, blocks.map(|(bb, _)| bb), self, vis) } }