1use super::super::modes::*;
2use super::super::prelude::*;
3use super::super::set::*;
4use super::Loc;
5use super::option::*;
6use super::pcm;
7use super::pcm::PCM;
8use super::relations::*;
9
10verus! {
11
12broadcast use super::super::set::group_set_axioms;
13
14#[verifier::accept_recursive_types(RA)]
16pub tracked struct Resource<RA: ResourceAlgebra> {
17 pcm: pcm::Resource<Option<RA>>,
18}
19
20#[verifier::accept_recursive_types(RA)]
21pub tracked struct ResourceRef<'a, RA: ResourceAlgebra> {
22 pcm: &'a pcm::Resource<Option<RA>>,
23}
24
25impl<RA: ResourceAlgebra> Resource<RA> {
26 pub proof fn as_ref(tracked &self) -> (tracked r: ResourceRef<'_, RA>)
27 ensures
28 self.loc() == r.loc(),
29 self.value() == r.value(),
30 {
31 use_type_invariant(self);
32 ResourceRef { pcm: &self.pcm }
33 }
34}
35
36pub trait ResourceAlgebra: Sized {
48 spec fn valid(self) -> bool;
50
51 spec fn op(a: Self, b: Self) -> Self;
55
56 proof fn associative(a: Self, b: Self, c: Self)
58 ensures
59 Self::op(a, Self::op(b, c)) == Self::op(Self::op(a, b), c),
60 ;
61
62 proof fn commutative(a: Self, b: Self)
64 ensures
65 Self::op(a, b) == Self::op(b, a),
66 ;
67
68 proof fn valid_op(a: Self, b: Self)
71 requires
72 Self::op(a, b).valid(),
73 ensures
74 a.valid(),
75 ;
76}
77
78impl<RA: ResourceAlgebra> Resource<RA> {
81 #[verifier::type_invariant]
82 spec fn inv(self) -> bool {
83 self.pcm.value() is Some
84 }
85
86 pub closed spec fn value(self) -> RA {
88 self.pcm.value()->Some_0
89 }
90
91 pub closed spec fn loc(self) -> Loc {
93 self.pcm.loc()
94 }
95
96 pub proof fn alloc(value: RA) -> (tracked out: Self)
99 requires
100 value.valid(),
101 ensures
102 out.value() == value,
103 {
104 let tracked pcm = pcm::Resource::alloc(Some(value));
105 Resource { pcm }
106 }
107
108 pub proof fn join(tracked self, tracked other: Self) -> (tracked out: Self)
112 requires
113 self.loc() == other.loc(),
114 ensures
115 out.loc() == self.loc(),
116 out.value() == RA::op(self.value(), other.value()),
117 {
118 use_type_invariant(&self);
119 use_type_invariant(&other);
120 let tracked pcm = self.pcm.join(other.pcm);
121 Resource { pcm }
122 }
123
124 pub proof fn split(tracked self, left: RA, right: RA) -> (tracked out: (Self, Self))
127 requires
128 self.value() == RA::op(left, right),
129 ensures
130 out.0.loc() == self.loc(),
131 out.1.loc() == self.loc(),
132 out.0.value() == left,
133 out.1.value() == right,
134 {
135 use_type_invariant(&self);
136 let tracked (left, right) = self.pcm.split(Some(left), Some(right));
137 (Resource { pcm: left }, Resource { pcm: right })
138 }
139
140 pub proof fn validate(tracked &self)
147 ensures
148 self.value().valid(),
149 {
150 use_type_invariant(self);
151 self.pcm.validate();
152 }
153
154 pub proof fn update_nondeterministic(tracked self, new_values: Set<RA>) -> (tracked out: Self)
157 requires
158 frame_preserving_update_nondeterministic_opt(self.value(), new_values),
159 ensures
160 out.loc() == self.loc(),
161 new_values.contains(out.value()),
162 {
163 use_type_invariant(&self);
164 let opt_new_values = new_values.map(|v| Some(v));
165 lemma_frame_preserving_update_nondeterministic_opt(self.value(), new_values);
166 let tracked pcm = self.pcm.update_nondeterministic(opt_new_values);
167 Resource { pcm }
168 }
169
170 pub proof fn update(tracked self, new_value: RA) -> (tracked out: Self)
177 requires
178 frame_preserving_update_opt(self.value(), new_value),
179 ensures
180 out.loc() == self.loc(),
181 out.value() == new_value,
182 {
183 let new_values = set![new_value];
184 assert(new_values.contains(new_value));
185 self.update_nondeterministic(new_values)
186 }
187
188 pub proof fn extract(tracked &mut self) -> (tracked other: Self)
191 ensures
192 other.loc() == old(self).loc(),
193 other.value() == old(self).value(),
194 {
195 self.validate();
196 let tracked mut other = Self::alloc(self.value());
197 tracked_swap(self, &mut other);
198 other
199 }
200
201 pub proof fn validate_2(tracked &mut self, tracked other: &ResourceRef<'_, RA>)
204 requires
205 old(self).loc() == other.loc(),
206 ensures
207 *self == *old(self),
208 RA::op(self.value(), other.value()).valid(),
209 {
210 use_type_invariant(&*self);
211 use_type_invariant(other);
212 self.pcm.validate_2(&other.pcm);
213 }
214
215 pub proof fn update_nondeterministic_with_shared(
217 tracked self,
218 tracked other: &ResourceRef<'_, RA>,
219 new_values: Set<RA>,
220 ) -> (tracked out: Self)
221 requires
222 self.loc() == other.loc(),
223 frame_preserving_update_nondeterministic_opt(
224 RA::op(self.value(), other.value()),
225 set_op(new_values, other.value()),
226 ),
227 ensures
228 out.loc() == self.loc(),
229 new_values.contains(out.value()),
230 {
231 use_type_invariant(&self);
232 use_type_invariant(other);
233 let a = RA::op(self.value(), other.value());
234 let bs = set_op(new_values, other.value());
235
236 lemma_frame_preserving_update_nondeterministic_opt(a, bs);
237 lemma_set_op_opt(new_values, other.value());
238
239 let new_values_opt = new_values.map(|v| Some(v));
240 let tracked pcm = self.pcm.update_nondeterministic_with_shared(&other.pcm, new_values_opt);
241 Resource { pcm }
242 }
243
244 pub proof fn update_with_shared(
247 tracked self,
248 tracked other: &ResourceRef<'_, RA>,
249 new_value: RA,
250 ) -> (tracked out: Self)
251 requires
252 self.loc() == other.loc(),
253 frame_preserving_update_opt(
254 RA::op(self.value(), other.value()),
255 RA::op(new_value, other.value()),
256 ),
257 ensures
258 out.loc() == self.loc(),
259 out.value() == new_value,
260 {
261 let new_values = set![new_value];
262 let so = set_op(new_values, other.value());
263 assert(new_values.contains(new_value));
264 assert(so == set![new_value].map(|n| RA::op(new_value, other.value())));
265 assert(so.contains(RA::op(new_value, other.value())));
266 self.update_nondeterministic_with_shared(other, new_values)
267 }
268}
269
270impl<'a, RA: ResourceAlgebra> ResourceRef<'a, RA> {
271 #[verifier::type_invariant]
272 spec fn inv(self) -> bool {
273 self.pcm.value() is Some
274 }
275
276 pub closed spec fn loc(self) -> Loc {
277 self.pcm.loc()
278 }
279
280 pub closed spec fn value(self) -> RA {
281 self.pcm.value()->Some_0
282 }
283
284 pub proof fn validate(tracked &self)
287 ensures
288 self.value().valid(),
289 {
290 use_type_invariant(self);
291 self.pcm.validate();
292 }
293
294 pub proof fn join_shared(tracked &self, tracked other: &Self) -> (tracked out: Self)
297 requires
298 self.loc() == other.loc(),
299 ensures
300 out.loc() == self.loc(),
301 incl(self.value(), out.value()) || self.value() == out.value(),
302 incl(other.value(), out.value()) || other.value() == out.value(),
303 {
304 use_type_invariant(self);
305 use_type_invariant(other);
306 let tracked pcm = self.pcm.join_shared(&other.pcm);
307 assert(pcm.value() is Some);
308 assert(incl(Some(self.value()), pcm.value()));
309 assert(incl(Some(other.value()), pcm.value()));
310 lemma_incl_opt_rev(self.value(), pcm.value()->Some_0);
311 lemma_incl_opt_rev(other.value(), pcm.value()->Some_0);
312 ResourceRef { pcm }
313 }
314
315 pub proof fn weaken(tracked &self, target: RA) -> (tracked out: ResourceRef<'a, RA>)
317 requires
318 incl(target, self.value()),
319 ensures
320 out.loc() == self.loc(),
321 out.value() == target,
322 {
323 use_type_invariant(self);
324 lemma_incl_opt(target, self.value());
325 let tracked pcm = self.pcm.weaken(Some(target));
326 ResourceRef { pcm }
327 }
328
329 pub proof fn duplicate_previous(tracked &self, value: RA) -> (tracked out: Resource<RA>)
332 requires
333 frame_preserving_update_opt(self.value(), RA::op(value, self.value())),
334 ensures
335 out.loc() == self.loc(),
336 out.value() == value,
337 {
338 use_type_invariant(self);
339 let b = RA::op(value, self.value());
340 lemma_frame_preserving_opt(self.value(), b);
341 let tracked pcm = self.pcm.duplicate_previous(Some(value));
342 Resource { pcm }
343 }
344
345 pub proof fn join_shared_to_target(
347 tracked &self,
348 tracked other: &Self,
349 target: RA,
350 ) -> (tracked out: Self)
351 requires
352 self.loc() == other.loc(),
353 conjunct_shared(Some(self.value()), Some(other.value()), Some(target)),
354 ensures
355 out.loc() == self.loc(),
356 out.value() == target,
357 {
358 let tracked joined = self.join_shared(other);
359 joined.validate();
360 assert(Some(joined.value()).valid());
361 if self.value() == joined.value() {
362 Some(self.value()).op_unit();
363 assert(incl(Some(self.value()), Some(joined.value())));
364 } else {
365 lemma_incl_opt(self.value(), joined.value());
366 }
367 if other.value() == joined.value() {
368 Some(other.value()).op_unit();
369 assert(incl(Some(other.value()), Some(joined.value())));
370 } else {
371 lemma_incl_opt(other.value(), joined.value());
372 }
373 assert(incl(Some(target), Some(joined.value())));
374 lemma_incl_opt_rev(target, joined.value());
375 if joined.value() == target {
376 joined
377 } else {
378 joined.weaken(target)
379 }
380 }
381}
382
383}