vstd_extra/
drop_tracking.rs1use core::ops::Deref;
2use vstd::prelude::*;
3use vstd::resource::Loc;
4
5use crate::resource::ghost_resource::excl::ExclusiveGhost;
6
7verus! {
8
9pub trait TrackDrop: Sized {
30 type State;
32
33 type Obligation;
39
40 spec fn tracked_redeem_requires(self, s: Self::State) -> bool;
41
42 spec fn tracked_redeem_ensures(
43 self,
44 s0: Self::State,
45 s1: Self::State,
46 obl: Self::Obligation,
47 ) -> bool;
48
49 proof fn tracked_redeem(self, tracked s: &mut Self::State) -> (tracked obl: Self::Obligation)
51 requires
52 self.tracked_redeem_requires(*old(s)),
53 ensures
54 self.tracked_redeem_ensures(*old(s), *final(s), obl),
55 ;
56
57 spec fn drop_requires(self, s: Self::State, obl: Self::Obligation) -> bool;
59
60 spec fn drop_ensures(self, s0: Self::State, s1: Self::State, obl: Self::Obligation) -> bool;
62}
63
64pub trait Drop: TrackDrop {
65 fn drop(self, Tracked(s): Tracked<&mut Self::State>, Tracked(obl): Tracked<Self::Obligation>)
66 requires
67 self.drop_requires(*old(s), obl),
68 ensures
69 self.drop_ensures(*old(s), *final(s), obl),
70 ;
71}
72
73} #[verus_verify]
75pub struct ManuallyDrop<T: TrackDrop> {
76 value: core::mem::ManuallyDrop<T>,
77 #[cfg(verus_keep_ghost_body)]
78 tracked_obligation: Tracked<T::Obligation>,
79}
80
81#[verus_verify]
82impl<T: TrackDrop> ManuallyDrop<T> {
83 #[verus_spec(res =>
84 with
85 Tracked(obligation): Tracked<T::Obligation>,
86 ensures
87 res@ == t,
88 res.obligation() == obligation,
89 )]
90 pub fn new(t: T) -> Self {
91 proof_with! { tracked_obligation: Tracked(obligation) }
92 Self {
93 value: core::mem::ManuallyDrop::new(t),
94 }
95 }
96
97 #[verus_spec(res =>
98 with
99 -> obligation: Tracked<T::Obligation>,
100 ensures
101 res == slot@,
102 obligation@ == slot.obligation(),
103 )]
104 pub fn into_inner(slot: Self) -> T {
105 proof_decl! {
106 let tracked obligation = slot.tracked_obligation.get();
107 }
108 proof_with!(|= Tracked(obligation));
109 std::mem::ManuallyDrop::<T>::into_inner(slot.value)
110 }
111}
112
113#[verus_verify]
114impl<T: TrackDrop> Deref for ManuallyDrop<T> {
115 type Target = T;
116
117 #[verus_spec(res =>
118 ensures
119 *res == self@,
120 )]
121 fn deref(&self) -> &Self::Target {
122 &self.value
123 }
124}
125
126verus! {
127
128impl<T: TrackDrop> View for ManuallyDrop<T> {
129 type V = T;
130
131 closed spec fn view(&self) -> (res: Self::V) {
132 self.value@
133 }
134}
135
136impl<T: TrackDrop> ManuallyDrop<T> {
137 pub closed spec fn obligation(self) -> T::Obligation {
138 self.tracked_obligation@
139 }
140}
141
142} verus! {
144
145#[verifier::reject_recursive_types(R)]
146pub tracked struct DropObligation<R> {
147 inner: ExclusiveGhost<R>,
148}
149
150impl<R> DropObligation<R> {
151 pub closed spec fn value(self) -> R {
152 self.inner.view()
153 }
154
155 pub closed spec fn id(self) -> Loc {
157 self.inner.id()
158 }
159
160 pub proof fn tracked_mint(value: R) -> (tracked res: DropObligation<R>)
162 ensures
163 res.value() == value,
164 {
165 DropObligation { inner: ExclusiveGhost::alloc(value) }
166 }
167
168 pub proof fn validate_with_other(tracked &mut self, tracked other: &Self)
170 ensures
171 *old(self) == *final(self),
172 final(self).id() != other.id(),
173 {
174 self.inner.validate_with_other(&other.inner);
175 }
176}
177
178}