use rustc_middle::ty::TyCtxt;
use super::{
contract::Property,
forward_visit::{ForwardVisitResult, ForwardVisitor},
helpers::{Callsite, CallsiteLocation},
path::Path,
path_refine::{BackwardItem, BackwardVisitor, RelevantMirItems},
smt_check::{SmtCheckResult, SmtChecker},
};
pub struct VerifyEngine<'tcx> {
backward: BackwardVisitor<'tcx>,
forward: ForwardVisitor<'tcx>,
smt: SmtChecker<'tcx>,
}
impl<'tcx> VerifyEngine<'tcx> {
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
Self {
backward: BackwardVisitor::new(tcx),
forward: ForwardVisitor::new(tcx),
smt: SmtChecker::new(tcx),
}
}
pub fn check_callsite(
&self,
callsite: &Callsite<'tcx>,
path: &Path,
property: &Property<'tcx>,
) -> (ForwardVisitResult<'tcx>, SmtCheckResult) {
let backward = self.backward.visit(callsite, path, property);
let forward = self.forward.visit(&backward);
let smt = self.smt.check(callsite, property, &forward);
(forward, smt)
}
pub fn check_invariant(
&self,
def_id: rustc_hir::def_id::DefId,
checkpoint: CallsiteLocation,
path: &Path,
property: &Property<'tcx>,
invariants: &[Property<'tcx>],
is_constructor: bool,
) -> (RelevantMirItems<'tcx>, ForwardVisitResult<'tcx>, SmtCheckResult) {
let mut backward = self
.backward
.visit_for_checkpoint(def_id, checkpoint, path, property);
if !is_constructor {
let mut items: Vec<BackwardItem<'tcx>> = invariants
.iter()
.map(|inv| BackwardItem::ContractFact {
property: inv.clone(),
})
.collect();
items.extend(backward.items.clone());
backward.items = items;
}
let forward = self.forward.visit(&backward);
let smt = self.smt.check_for_checkpoint(def_id, property, &forward);
(backward, forward, smt)
}
}