vstd/resource/
ghost_var.rs1#[cfg(verus_keep_ghost)]
2use super::super::modes::tracked_swap;
3use super::super::prelude::*;
4use super::Loc;
5use super::frac::FracGhost;
6
7verus! {
8
9pub tracked struct GhostVar<T> {
11 frac: FracGhost<T>,
12}
13
14impl<T> GhostVar<T> {
15 #[verifier::type_invariant]
16 spec fn inv(self) -> bool {
17 self.frac.frac() == (1 as real) / (2 as real)
18 }
19
20 pub closed spec fn id(self) -> Loc {
21 self.frac.id()
22 }
23
24 pub closed spec fn view(self) -> T {
25 self.frac.view()
26 }
27}
28
29pub tracked struct GhostVarAuth<T> {
56 frac: FracGhost<T>,
57}
58
59impl<T> GhostVarAuth<T> {
60 #[verifier::type_invariant]
61 spec fn inv(self) -> bool {
62 self.frac.frac() == (1 as real) / (2 as real)
63 }
64
65 pub closed spec fn id(self) -> Loc {
66 self.frac.id()
67 }
68
69 pub closed spec fn view(self) -> T {
70 self.frac.view()
71 }
72
73 pub proof fn new(v: T) -> (tracked result: (GhostVarAuth<T>, GhostVar<T>))
75 ensures
76 result.0.id() == result.1.id(),
77 result.0@ == v,
78 result.1@ == v,
79 {
80 let tracked mut f = FracGhost::<T>::new(v);
81 let tracked v = GhostVar::<T> { frac: f.split() };
82 let tracked a = GhostVarAuth::<T> { frac: f };
83 (a, v)
84 }
85
86 pub proof fn agree(tracked &self, tracked v: &GhostVar<T>)
88 requires
89 self.id() == v.id(),
90 ensures
91 self@ == v@,
92 {
93 self.frac.agree(&v.frac)
94 }
95
96 pub proof fn update(tracked &mut self, tracked v: &mut GhostVar<T>, new_val: T)
98 requires
99 old(self).id() == old(v).id(),
100 ensures
101 self.id() == old(self).id(),
102 v.id() == old(v).id(),
103 old(self)@ == old(v)@,
104 self@ == new_val,
105 v@ == new_val,
106 {
107 let tracked (mut ms, mut mv) = Self::new(new_val);
108 tracked_swap(self, &mut ms);
109 tracked_swap(v, &mut mv);
110 use_type_invariant(&ms);
111 use_type_invariant(&mv);
112 let tracked mut msfrac = ms.frac;
113 msfrac.combine(mv.frac);
114 msfrac.update(new_val);
115 let tracked mut nv = GhostVar::<T> { frac: msfrac.split() };
116 let tracked mut ns = Self { frac: msfrac };
117 tracked_swap(self, &mut ns);
118 tracked_swap(v, &mut nv);
119 }
120}
121
122}