Skip to content

Commit 338f73e

Browse files
committed
resource: isolate fractional opt
1 parent d8659d9 commit 338f73e

File tree

2 files changed

+344
-334
lines changed

2 files changed

+344
-334
lines changed

source/vstd/resource/frac.rs

Lines changed: 0 additions & 334 deletions
Original file line numberDiff line numberDiff line change
@@ -305,338 +305,4 @@ impl<T> FracGhost<T> {
305305
}
306306
}
307307

308-
/////// Fractional tokens that allow borrowing of resources
309-
enum FractionalCarrierOpt<T> {
310-
Value { v: Option<T>, frac: real },
311-
Empty,
312-
Invalid,
313-
}
314-
315-
impl<T> Protocol<(), T> for FractionalCarrierOpt<T> {
316-
closed spec fn op(self, other: Self) -> Self {
317-
match self {
318-
FractionalCarrierOpt::Invalid => FractionalCarrierOpt::Invalid,
319-
FractionalCarrierOpt::Empty => other,
320-
FractionalCarrierOpt::Value { v: sv, frac: s_frac } => match other {
321-
FractionalCarrierOpt::Invalid => FractionalCarrierOpt::Invalid,
322-
FractionalCarrierOpt::Empty => self,
323-
FractionalCarrierOpt::Value { v: ov, frac: o_frac } => {
324-
if sv != ov {
325-
FractionalCarrierOpt::Invalid
326-
} else if s_frac <= 0 as real || o_frac <= 0 as real || s_frac + o_frac
327-
> 1 as real {
328-
FractionalCarrierOpt::Invalid
329-
} else {
330-
FractionalCarrierOpt::Value { v: sv, frac: s_frac + o_frac }
331-
}
332-
},
333-
},
334-
}
335-
}
336-
337-
closed spec fn rel(self, s: Map<(), T>) -> bool {
338-
match self {
339-
FractionalCarrierOpt::Value { v, frac } => {
340-
(match v {
341-
Some(v0) => s.dom().contains(()) && s[()] == v0,
342-
None => s =~= map![],
343-
}) && frac == 1 as real
344-
},
345-
FractionalCarrierOpt::Empty => false,
346-
FractionalCarrierOpt::Invalid => false,
347-
}
348-
}
349-
350-
closed spec fn unit() -> Self {
351-
FractionalCarrierOpt::Empty
352-
}
353-
354-
proof fn commutative(a: Self, b: Self) {
355-
}
356-
357-
proof fn associative(a: Self, b: Self, c: Self) {
358-
}
359-
360-
proof fn op_unit(a: Self) {
361-
}
362-
}
363-
364-
/// Token that maintains fractional access to some resource.
365-
/// This allows multiple clients to obtain shared references to some resource
366-
/// via `borrow`.
367-
pub struct Frac<T> {
368-
r: StorageResource<(), T, FractionalCarrierOpt<T>>,
369-
}
370-
371-
/// Token that represents the "empty" state of a fractional resource system.
372-
/// See [`Frac`] for more information.
373-
pub struct Empty<T> {
374-
r: StorageResource<(), T, FractionalCarrierOpt<T>>,
375-
}
376-
377-
impl<T> Frac<T> {
378-
#[verifier::type_invariant]
379-
spec fn inv(self) -> bool {
380-
self.r.value() matches FractionalCarrierOpt::Value { v: Some(_), .. }
381-
}
382-
383-
pub closed spec fn id(self) -> Loc {
384-
self.r.loc()
385-
}
386-
387-
pub closed spec fn resource(self) -> T {
388-
self.r.value()->v.unwrap()
389-
}
390-
391-
pub closed spec fn frac(self) -> real {
392-
self.r.value()->frac
393-
}
394-
395-
pub open spec fn valid(self, id: Loc, frac: real) -> bool {
396-
&&& self.id() == id
397-
&&& self.frac() == frac
398-
}
399-
400-
/// Create a fractional token that maintains shared access to the input resource.
401-
pub proof fn new(tracked v: T) -> (tracked result: Self)
402-
ensures
403-
result.frac() == 1 as real,
404-
result.resource() == v,
405-
{
406-
let f = FractionalCarrierOpt::<T>::Value { v: Some(v), frac: 1 as real };
407-
let tracked mut m = Map::<(), T>::tracked_empty();
408-
m.tracked_insert((), v);
409-
let tracked r = StorageResource::alloc(f, m);
410-
Self { r }
411-
}
412-
413-
/// Two tokens agree on values of the underlying resource.
414-
pub proof fn agree(tracked self: &Self, tracked other: &Self)
415-
requires
416-
self.id() == other.id(),
417-
ensures
418-
self.resource() == other.resource(),
419-
{
420-
use_type_invariant(self);
421-
use_type_invariant(other);
422-
let tracked joined = self.r.join_shared(&other.r);
423-
joined.validate();
424-
}
425-
426-
// This helper is needed to bypass the type invariant temporarily
427-
proof fn split_to_helper(
428-
tracked r: &mut StorageResource<(), T, FractionalCarrierOpt<T>>,
429-
frac: real,
430-
) -> (tracked result: Self)
431-
requires
432-
(0 as real) < frac < old(r).value()->frac,
433-
old(r).value() matches FractionalCarrierOpt::Value { v: Some(_), .. },
434-
ensures
435-
r.loc() == old(r).loc(),
436-
result.id() == old(r).loc(),
437-
r.value()->v.unwrap() == old(r).value()->v.unwrap(),
438-
result.resource() == old(r).value()->v.unwrap(),
439-
r.value()->frac + result.frac() == old(r).value()->frac,
440-
result.frac() == frac,
441-
r.value() matches FractionalCarrierOpt::Value { v: Some(_), .. },
442-
{
443-
r.validate();
444-
let tracked mut r1 = StorageResource::alloc(
445-
FractionalCarrierOpt::Value { v: None, frac: 1 as real },
446-
Map::tracked_empty(),
447-
);
448-
tracked_swap(r, &mut r1);
449-
let tracked (r1, r2) = r1.split(
450-
FractionalCarrierOpt::Value { v: r1.value()->v, frac: r1.value()->frac - frac },
451-
FractionalCarrierOpt::Value { v: r1.value()->v, frac: frac },
452-
);
453-
*r = r1;
454-
Self { r: r2 }
455-
}
456-
457-
/// Split one resource into two resources whose quantities sum to the original.
458-
/// The returned token has quantity `result_frac`; the new value of the input token has
459-
/// quantity `old(self).frac() - result_frac`.
460-
pub proof fn split_to(tracked &mut self, result_frac: real) -> (tracked result: Self)
461-
requires
462-
0 as real < result_frac < old(self).frac(),
463-
ensures
464-
self.id() == old(self).id(),
465-
result.id() == old(self).id(),
466-
self.resource() == old(self).resource(),
467-
result.resource() == old(self).resource(),
468-
self.frac() == old(self).frac() - result_frac,
469-
result.frac() == result_frac,
470-
{
471-
use_type_invariant(&*self);
472-
Self::split_to_helper(&mut self.r, result_frac)
473-
}
474-
475-
/// Split one resource by half into two resources whose quantities sum to the original.
476-
/// The returned token has quantity `n`; the new value of the input token has
477-
/// quantity `old(self).frac() - n`.
478-
pub proof fn split(tracked &mut self) -> (tracked result: Self)
479-
ensures
480-
self.id() == old(self).id(),
481-
result.id() == old(self).id(),
482-
self.resource() == old(self).resource(),
483-
result.resource() == old(self).resource(),
484-
self.frac() == old(self).frac() / 2 as real,
485-
result.frac() == old(self).frac() / 2 as real,
486-
{
487-
use_type_invariant(&*self);
488-
self.r.validate();
489-
self.split_to(self.frac() / 2 as real)
490-
}
491-
492-
/// Combine two tokens, summing their quantities.
493-
pub proof fn combine(tracked &mut self, tracked other: Self)
494-
requires
495-
old(self).id() == other.id(),
496-
ensures
497-
self.id() == old(self).id(),
498-
self.resource() == old(self).resource(),
499-
self.resource() == other.resource(),
500-
self.frac() == old(self).frac() + other.frac(),
501-
{
502-
use_type_invariant(&*self);
503-
Self::combine_helper(&mut self.r, other);
504-
}
505-
506-
// This helper is needed to temporarily bypass the type invariant
507-
proof fn combine_helper(
508-
tracked r: &mut StorageResource<(), T, FractionalCarrierOpt<T>>,
509-
tracked other: Self,
510-
)
511-
requires
512-
old(r).loc() == other.id(),
513-
old(r).value() matches FractionalCarrierOpt::Value { v: Some(_), .. },
514-
ensures
515-
r.loc() == old(r).loc(),
516-
r.value()->v.unwrap() == old(r).value()->v.unwrap(),
517-
r.value()->v.unwrap() == other.resource(),
518-
r.value()->frac == old(r).value()->frac + other.frac(),
519-
r.value() matches FractionalCarrierOpt::Value { v: Some(_), .. },
520-
{
521-
use_type_invariant(&other);
522-
r.validate();
523-
let tracked mut r1 = StorageResource::alloc(
524-
FractionalCarrierOpt::Value { v: None, frac: 1 as real },
525-
Map::tracked_empty(),
526-
);
527-
tracked_swap(r, &mut r1);
528-
r1.validate_with_shared(&other.r);
529-
*r = StorageResource::join(r1, other.r);
530-
}
531-
532-
/// Allowed values for a token's quantity.
533-
pub proof fn bounded(tracked &self)
534-
ensures
535-
0 as real < self.frac() <= 1 as real,
536-
{
537-
use_type_invariant(self);
538-
let (x, _) = self.r.validate();
539-
}
540-
541-
/// Obtain shared access to the underlying resource.
542-
pub proof fn borrow(tracked &self) -> (tracked ret: &T)
543-
ensures
544-
ret == self.resource(),
545-
{
546-
use_type_invariant(self);
547-
StorageResource::guard(&self.r, map![() => self.resource()]).tracked_borrow(())
548-
}
549-
550-
/// Reclaim full ownership of the underlying resource.
551-
pub proof fn take_resource(tracked self) -> (tracked pair: (T, Empty<T>))
552-
requires
553-
self.frac() == 1 as real,
554-
ensures
555-
pair.0 == self.resource(),
556-
pair.1.id() == self.id(),
557-
{
558-
use_type_invariant(&self);
559-
self.r.validate();
560-
561-
let p1 = self.r.value();
562-
let p2 = FractionalCarrierOpt::Value { v: None, frac: 1 as real };
563-
let b2 = map![() => self.resource()];
564-
assert forall|q: FractionalCarrierOpt<T>, t1: Map<(), T>|
565-
#![all_triggers]
566-
FractionalCarrierOpt::rel(FractionalCarrierOpt::op(p1, q), t1) implies exists|
567-
t2: Map<(), T>,
568-
|
569-
#![all_triggers]
570-
FractionalCarrierOpt::rel(FractionalCarrierOpt::op(p2, q), t2) && t2.dom().disjoint(
571-
b2.dom(),
572-
) && t1 =~= t2.union_prefer_right(b2) by {
573-
let t2 = map![];
574-
assert(FractionalCarrierOpt::rel(FractionalCarrierOpt::op(p2, q), t2));
575-
assert(t2.dom().disjoint(b2.dom()));
576-
assert(t1 =~= t2.union_prefer_right(b2));
577-
}
578-
579-
let tracked Self { r } = self;
580-
let tracked (new_r, mut m) = r.withdraw(p2, b2);
581-
let tracked emp = Empty { r: new_r };
582-
let tracked resource = m.tracked_remove(());
583-
(resource, emp)
584-
}
585-
}
586-
587-
impl<T> Empty<T> {
588-
#[verifier::type_invariant]
589-
spec fn inv(self) -> bool {
590-
&&& self.r.value() matches FractionalCarrierOpt::Value { v: None, frac }
591-
&&& frac == 1 as real
592-
}
593-
594-
pub closed spec fn id(self) -> Loc {
595-
self.r.loc()
596-
}
597-
598-
pub proof fn new(tracked v: T) -> (tracked result: Self) {
599-
let f = FractionalCarrierOpt::<T>::Value { v: None, frac: 1 as real };
600-
let tracked mut m = Map::<(), T>::tracked_empty();
601-
let tracked r = StorageResource::alloc(f, m);
602-
Self { r }
603-
}
604-
605-
/// Give up ownership of a resource and obtain a [`Frac`] token.
606-
pub proof fn put_resource(tracked self, tracked resource: T) -> (tracked frac: Frac<T>)
607-
ensures
608-
frac.id() == self.id(),
609-
frac.resource() == resource,
610-
frac.frac() == 1 as real,
611-
{
612-
use_type_invariant(&self);
613-
self.r.validate();
614-
615-
let p1 = self.r.value();
616-
let b1 = map![() => resource];
617-
let p2 = FractionalCarrierOpt::Value { v: Some(resource), frac: 1 as real };
618-
619-
assert forall|q: FractionalCarrierOpt<T>, t1: Map<(), T>|
620-
#![all_triggers]
621-
FractionalCarrierOpt::rel(FractionalCarrierOpt::op(p1, q), t1) implies exists|
622-
t2: Map<(), T>,
623-
|
624-
#![all_triggers]
625-
FractionalCarrierOpt::rel(FractionalCarrierOpt::op(p2, q), t2) && t1.dom().disjoint(
626-
b1.dom(),
627-
) && t1.union_prefer_right(b1) =~= t2 by {
628-
let t2 = map![() => resource];
629-
assert(FractionalCarrierOpt::rel(FractionalCarrierOpt::op(p2, q), t2)
630-
&& t1.dom().disjoint(b1.dom()) && t1.union_prefer_right(b1) =~= t2);
631-
}
632-
633-
let tracked mut m = Map::tracked_empty();
634-
m.tracked_insert((), resource);
635-
let tracked Self { r } = self;
636-
let tracked new_r = r.deposit(m, p2);
637-
let tracked f = Frac { r: new_r };
638-
f
639-
}
640-
}
641-
642308
} // verus!

0 commit comments

Comments
 (0)