Skip to content

Commit 32b1db6

Browse files
committed
Add more functions to the library
1 parent f8a2d4a commit 32b1db6

5 files changed

Lines changed: 193 additions & 9 deletions

File tree

ostd/src/sync/rwlock.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ impl<T, G> RwLock<T, G> {
322322
proof {lemma_consts_properties();}
323323
let tracked frac_perm = RwFrac::<T>::new(perm);
324324
proof_decl!{
325-
let tracked read_retract_token = TokenStorage::<V_MAX_READ_RETRACT_FRACS>::new(());
325+
let tracked read_retract_token = TokenStorage::<V_MAX_READ_RETRACT_FRACS>::alloc(());
326326
let tracked upread_retract_token = UniqueTokenStorage::alloc(());
327327
let tracked upreader_guard_token = UniqueTokenStorage::alloc(());
328328
}
Lines changed: 129 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,137 @@
11
//! Sum types for ghost resources.
22
use vstd::prelude::*;
3+
use vstd::pcm::Loc;
4+
use vstd::storage_protocol::*;
5+
6+
7+
use crate::resource::storage_protocol::csum::*;
8+
use crate::sum::*;
9+
310

411
verus! {
512

6-
pub ghost enum CsumP<A, B> {
7-
Unit,
8-
Cinl(A),
9-
Cinr(B),
10-
CsumInvalid,
13+
/// `SumResourceStorage` is a storage resource that stores either an A or a B, but not both.
14+
pub tracked struct SumResourceStorage<A, B> {
15+
tracked r: StorageResource<(), Sum<A, B>, CsumP<A, B>>,
16+
}
17+
18+
impl<A,B> SumResourceStorage<A, B>
19+
{
20+
pub closed spec fn id(self) -> Loc {
21+
self.r.loc()
22+
}
23+
24+
pub closed spec fn protocol_monoid(self) -> CsumP<A, B> {
25+
self.r.value()
26+
}
27+
28+
pub open spec fn is_empty(self) -> bool {
29+
self.protocol_monoid() is Unit
30+
}
31+
32+
pub open spec fn is_left(self) -> bool {
33+
self.protocol_monoid() is Cinl
34+
}
35+
36+
pub open spec fn is_right(self) -> bool {
37+
self.protocol_monoid() is Cinr
38+
}
39+
40+
pub open spec fn resource(self) -> Sum<A, B> {
41+
self.protocol_monoid().to_sum()
42+
}
43+
44+
pub proof fn alloc_empty() -> (tracked res:Self)
45+
ensures
46+
res.is_empty(),
47+
{
48+
let tracked r = StorageResource::alloc(CsumP::Unit, Map::tracked_empty());
49+
SumResourceStorage { r }
50+
}
51+
52+
pub proof fn alloc_left(tracked a: A) -> (tracked res: Self)
53+
ensures
54+
res.is_left(),
55+
res.resource() is Left,
56+
res.resource()->Left_0 == a,
57+
{
58+
let tracked mut m = Map::tracked_empty();
59+
m.tracked_insert((), Sum::Left(a));
60+
let tracked r = StorageResource::alloc(CsumP::Cinl(a), m);
61+
SumResourceStorage { r }
62+
}
63+
64+
pub proof fn alloc_right(tracked b: B) -> (tracked res: Self)
65+
ensures
66+
res.is_right(),
67+
res.resource() is Right,
68+
res.resource()->Right_0 == b,
69+
{
70+
let tracked mut m = Map::tracked_empty();
71+
m.tracked_insert((), Sum::Right(b));
72+
let tracked r = StorageResource::alloc(CsumP::Cinr(b), m);
73+
SumResourceStorage { r }
74+
}
75+
76+
pub proof fn tracked_take(tracked self) -> (tracked res: Sum<A, B>)
77+
requires
78+
self.is_left() || self.is_right(),
79+
ensures
80+
res == self.resource(),
81+
{
82+
self.protocol_monoid().lemma_csum_withdraws();
83+
let tracked r = self.r;
84+
let tracked (_,mut m) = r.withdraw(CsumP::Unit, map![() => self.protocol_monoid().to_sum()]);
85+
m.tracked_remove(())
86+
}
87+
88+
pub proof fn tracked_take_left(tracked self) -> (tracked res: A)
89+
requires
90+
self.is_left(),
91+
ensures
92+
res == self.resource()->Left_0,
93+
{
94+
let tracked sum = self.tracked_take();
95+
sum.tracked_take_left()
96+
}
97+
98+
pub proof fn tracked_take_right(tracked self) -> (tracked res: B)
99+
requires
100+
self.is_right(),
101+
ensures
102+
res == self.resource()->Right_0,
103+
{
104+
let tracked sum = self.tracked_take();
105+
sum.tracked_take_right()
106+
}
107+
108+
pub proof fn tracked_borrow(tracked &self) -> (tracked res: &Sum<A, B>)
109+
requires
110+
self.is_left() || self.is_right(),
111+
ensures
112+
*res == self.resource(),
113+
{
114+
StorageResource::guard(&self.r, map![() => self.resource()]).tracked_borrow(())
115+
}
116+
117+
pub proof fn tracked_borrow_left(tracked &self) -> (tracked res: &A)
118+
requires
119+
self.is_left(),
120+
ensures
121+
*res == self.resource()->Left_0,
122+
{
123+
self.tracked_borrow().tracked_borrow_left()
124+
}
125+
126+
pub proof fn tracked_borrow_right(tracked &self) -> (tracked res: &B)
127+
requires
128+
self.is_right(),
129+
ensures
130+
*res == self.resource()->Right_0,
131+
{
132+
self.tracked_borrow().tracked_borrow_right()
133+
}
134+
11135
}
12136

13137
} // verus!

vstd_extra/src/resource/ghost_resource/frac.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ impl<T> FracStorage<T> {
5252
}
5353

5454
/// Allocate a new fractional storage resource with full permission.
55-
pub proof fn new(tracked v: T) -> (tracked res: Self)
55+
pub proof fn alloc(tracked v: T) -> (tracked res: Self)
5656
ensures
5757
res.has_full_frac(),
5858
{

vstd_extra/src/resource/ghost_resource/tokens.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ impl<T, const TOTAL: u64> FracGhostStorage<T, TOTAL> {
6464
self.id
6565
}
6666

67-
pub proof fn new(value: T) -> (tracked res: Self)
67+
pub proof fn alloc(value: T) -> (tracked res: Self)
6868
requires
6969
TOTAL > 0,
7070
ensures

vstd_extra/src/resource/storage_protocol/csum.rs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,74 @@ use crate::sum::*;
88

99
verus!{
1010

11-
/// The Csum storage protocol.
11+
/// The Csum protocol monoid.
1212
pub ghost enum CsumP<A, B> {
1313
Unit,
1414
Cinl(A),
1515
Cinr(B),
1616
CsumInvalid,
1717
}
1818

19+
/// This protocol monoid allows exclusive ownership of either an A or a B, but not both. s
20+
impl<A,B> Protocol<(), Sum<A, B>> for CsumP<A, B> {
21+
open spec fn op(self, other: Self) -> Self {
22+
match (self, other) {
23+
(CsumP::Unit, x) => x,
24+
(x, CsumP::Unit) => x,
25+
_ => CsumP::CsumInvalid,
26+
}
27+
}
1928

29+
open spec fn rel(self, s: Map<(), Sum<A, B>>) -> bool {
30+
match self {
31+
CsumP::Unit => s.is_empty(),
32+
CsumP::Cinl(a) => s.contains_key(()) && s[()] == Sum::<A,B>::Left(a),
33+
CsumP::Cinr(b) => s.contains_key(()) && s[()] == Sum::<A,B>::Right(b),
34+
_ => false,
35+
}
36+
}
37+
38+
open spec fn unit() -> Self {
39+
CsumP::Unit
40+
}
41+
42+
proof fn commutative(a: Self, b: Self) {
43+
}
44+
45+
proof fn associative(a: Self, b: Self, c: Self) {
46+
}
47+
48+
proof fn op_unit(a: Self) {
49+
}
50+
}
51+
52+
53+
impl<A,B> CsumP<A, B> {
54+
55+
pub open spec fn to_sum(self) -> Sum<A, B> {
56+
match self {
57+
CsumP::Cinl(a) => Sum::Left(a),
58+
CsumP::Cinr(b) => Sum::Right(b),
59+
_ => arbitrary()
60+
}
61+
}
62+
63+
pub proof fn lemma_csum_withdraws(self)
64+
requires
65+
self is Cinl || self is Cinr,
66+
ensures
67+
withdraws(self, CsumP::Unit, map![() => self.to_sum()]),
68+
{
69+
let res_map = map![() => self.to_sum()];
70+
71+
assert forall |q: Self, t1: Map<(), Sum<A, B>>| Self::rel(Self::op(self, q), t1) implies
72+
exists |t2: Map<(), Sum<A, B>>| #[trigger] Self::rel(Self::op(CsumP::Unit, q), t2) &&
73+
t2.dom().disjoint(res_map.dom()) &&
74+
t1 == t2.union_prefer_right(res_map) by {
75+
let empty_map = Map::<(), Sum<A, B>>::empty();
76+
assert(Self::rel(Self::op(CsumP::Unit, q), empty_map) && empty_map.dom().disjoint(res_map.dom()) && Self::rel(Self::op(self, q), res_map));
77+
}
78+
}
79+
}
2080

2181
}

0 commit comments

Comments
 (0)