use super::{
common::{SmtCheckResult, SmtChecker, TypeSizeClass},
deref,
};
use crate::verify::{
contract::{Property, PropertyKind},
verifier::ForwardVisitResult,
helpers::Checkpoint,
report::CheckResult,
};
pub(crate) fn check<'tcx>(
checker: &SmtChecker<'tcx>,
checkpoint: &Checkpoint<'tcx>,
property: &Property<'tcx>,
forward: &ForwardVisitResult<'tcx>,
) -> SmtCheckResult {
let Some(required_ty) = checker.property_required_ty(checkpoint, property) else {
return SmtCheckResult::unknown("ValidPtr type could not be resolved");
};
match checker.type_size_class(checkpoint.caller, required_ty) {
TypeSizeClass::Zero => {
SmtCheckResult::proved(format!("ValidPtr proved by Size({required_ty:?}, 0)"))
}
TypeSizeClass::NonZero => {
let deref_property = primitive_property(property, PropertyKind::Deref);
let deref = deref::check(checker, checkpoint, &deref_property, forward);
match &deref.result {
CheckResult::Proved => {
SmtCheckResult::proved("ValidPtr proved: non-ZST target satisfies Deref")
}
CheckResult::Failed => SmtCheckResult {
result: CheckResult::Failed,
query: None,
notes: vec![String::from(
"ValidPtr failed: non-ZST target does not satisfy Deref",
)],
},
CheckResult::Unknown => {
SmtCheckResult::unknown("ValidPtr unknown: non-ZST Deref is not proved")
}
}
.with_note(format!("primitive Deref via SMT: {:?}", deref.result))
}
TypeSizeClass::Unknown => {
let deref_property = primitive_property(property, PropertyKind::Deref);
let deref = deref::check(checker, checkpoint, &deref_property, forward);
match &deref.result {
CheckResult::Proved => SmtCheckResult::proved(
"ValidPtr proved: Deref holds, so the formula holds for zero and non-zero sizes",
),
CheckResult::Failed | CheckResult::Unknown => SmtCheckResult::unknown(
"ValidPtr unknown: type size is unresolved and Deref is not proved",
),
}
.with_note("type size: Unknown")
.with_note(format!("primitive Deref via SMT: {:?}", deref.result))
}
}
}
fn primitive_property<'tcx>(property: &Property<'tcx>, kind: PropertyKind) -> Property<'tcx> {
Property {
kind,
args: property.args.clone(),
}
}