use rustc_hir::def_id::DefId;
use rustc_middle::{mir::BasicBlock, ty::TyCtxt};
use crate::analysis::path::{
PathTree,
graph::{PathEnumerator, PathGraph},
};
use crate::verify::checkpoint::CheckpointLocation;
pub(crate) struct PathExtractor<'tcx> {
tcx: TyCtxt<'tcx>,
def_id: DefId,
allow_repeat: usize,
}
impl<'tcx> PathExtractor<'tcx> {
pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: DefId, allow_repeat: usize) -> Self {
Self {
tcx,
def_id,
allow_repeat,
}
}
pub(crate) fn run(self) -> PathTree {
let mut graph = PathGraph::new(self.tcx, self.def_id);
graph.inline_callees();
graph.find_scc();
let mut tree = {
let mut enumerator = PathEnumerator::new(&graph);
enumerator.enumerate_paths_repeat(self.allow_repeat)
};
tree.set_block_fn(
graph
.cfg
.blocks
.iter()
.map(|b| (b.def_id, b.local_index))
.collect(),
graph.inline_bindings.clone(),
graph.inline_parents.clone(),
graph.inlined_call_blocks.clone(),
);
tree
}
}
#[derive(Clone, Debug)]
pub(crate) struct Path {
pub target: CheckpointLocation,
pub steps: Vec<PathStep>,
}
impl Path {
pub(crate) fn describe_indices(&self) -> String {
let mut indices: Vec<usize> = Vec::new();
for step in &self.steps {
match step {
PathStep::Block(b) => indices.push(b.as_usize()),
PathStep::Checkpoint(l) => {
let bb = l.block.as_usize();
if indices.last() != Some(&bb) {
indices.push(bb);
}
}
}
}
format!("{:?}", indices)
}
}
#[derive(Clone, Debug)]
pub(crate) enum PathStep {
Block(BasicBlock),
Checkpoint(CheckpointLocation),
}