Skip to main content

warp_types_pdr/
session.rs

1//! PDR session with lifetime-branded phase tracking.
2//!
3//! `PdrSession<'s, P>` follows the pattern from `warp_types_bmc::BmcSession`:
4//! - `'s` is an invariant lifetime brand (prevents cross-session mixing)
5//! - `P: Phase` tracks the current PDR workflow phase
6//! - Transitions consume the session and produce a new phase
7//! - Terminal states (`Safe`, `CounterexampleFound`, `Exhausted`) have no outgoing transitions
8//!
9//! Zero-sized — all PDR state (frames, obligations) lives inside `checker::check()`.
10
11use core::marker::PhantomData;
12use crate::phase::*;
13
14// ============================================================================
15// PDR session
16// ============================================================================
17
18/// A PDR session branded with lifetime `'s` and phase `P`.
19///
20/// Zero-sized — all phase tracking is compile-time only.
21#[must_use = "dropping a PdrSession loses phase tracking — use a transition or terminal"]
22pub struct PdrSession<'s, P: Phase> {
23    _brand: PhantomData<fn(&'s ()) -> &'s ()>,
24    _phase: PhantomData<P>,
25}
26
27impl<'s, P: Phase> PdrSession<'s, P> {
28    pub(crate) fn new() -> Self {
29        PdrSession {
30            _brand: PhantomData,
31            _phase: PhantomData,
32        }
33    }
34
35    /// Current phase name.
36    pub fn phase_name(&self) -> &'static str {
37        P::NAME
38    }
39}
40
41// ============================================================================
42// Phase transitions
43// ============================================================================
44
45impl<'s> PdrSession<'s, Init> {
46    /// Load a transition system model. Consumes Init, produces Modeled.
47    pub fn build_model(self) -> PdrSession<'s, Modeled> {
48        PdrSession::new()
49    }
50}
51
52impl<'s> PdrSession<'s, Modeled> {
53    /// Check result: property is safe (inductive invariant found).
54    pub fn check_safe(self) -> PdrSession<'s, Safe> {
55        PdrSession::new()
56    }
57
58    /// Check result: counterexample found.
59    pub fn check_counterexample(self) -> PdrSession<'s, CounterexampleFound> {
60        PdrSession::new()
61    }
62
63    /// Check result: frame budget exhausted.
64    pub fn check_exhausted(self) -> PdrSession<'s, Exhausted> {
65        PdrSession::new()
66    }
67}
68
69// ============================================================================
70// Entry point
71// ============================================================================
72
73/// Create a PDR session with a fresh lifetime brand.
74pub fn with_session<R>(f: impl for<'s> FnOnce(PdrSession<'s, Init>) -> R) -> R {
75    f(PdrSession::new())
76}