1#[cfg(creusot)]
2use crate::logic::any;
3use crate::{
4 logic::ra::{
5 RA,
6 update::{LocalUpdate, Update},
7 },
8 prelude::*,
9};
10
11pub enum Sum<T, U> {
16 Left(T),
17 Right(U),
18}
19
20impl<R1: RA, R2: RA> RA for Sum<R1, R2> {
21 #[logic(open)]
22 fn op(self, other: Self) -> Option<Self> {
23 match (self, other) {
24 (Self::Left(x), Self::Left(y)) => x.op(y).map_logic(|l| Self::Left(l)),
25 (Self::Right(x), Self::Right(y)) => x.op(y).map_logic(|r| Self::Right(r)),
26 _ => None,
27 }
28 }
29
30 #[logic(open)]
31 #[ensures(result == (exists<factor> self.op(factor) == Some(other)))]
32 fn incl(self, other: Self) -> bool {
33 match (self, other) {
34 (Self::Left(x), Self::Left(y)) => {
35 proof_assert!(forall<factor>
36 x.op(factor) == Some(y) ==> self.op(Self::Left(factor)) == Some(other));
37 x.incl(y)
38 }
39 (Self::Right(x), Self::Right(y)) => {
40 proof_assert!(forall<factor>
41 x.op(factor) == Some(y) ==> self.op(Self::Right(factor)) == Some(other));
42 x.incl(y)
43 }
44 _ => false,
45 }
46 }
47
48 #[logic(open, inline)]
49 #[ensures(#[trigger(self == other)] result == (self == other))]
50 fn eq(self, other: Self) -> bool {
51 match (self, other) {
52 (Sum::Left(s), Sum::Left(o)) => s.eq(o),
53 (Sum::Right(s), Sum::Right(o)) => s.eq(o),
54 _ => false,
55 }
56 }
57
58 #[logic(law)]
59 #[ensures(a.op(b) == b.op(a))]
60 fn commutative(a: Self, b: Self) {}
61
62 #[logic]
63 #[ensures(a.op(b).and_then_logic(|ab: Self| ab.op(c)) == b.op(c).and_then_logic(|bc| a.op(bc)))]
64 fn associative(a: Self, b: Self, c: Self) {}
65
66 #[logic(open)]
67 fn core(self) -> Option<Self> {
68 match self {
69 Self::Left(x) => x.core().map_logic(|l| Self::Left(l)),
70 Self::Right(x) => x.core().map_logic(|r| Self::Right(r)),
71 }
72 }
73
74 #[logic]
75 #[requires(self.core() != None)]
76 #[ensures({
77 let c = self.core().unwrap_logic();
78 c.op(c) == Some(c)
79 })]
80 #[ensures(self.core().unwrap_logic().op(self) == Some(self))]
81 fn core_idemp(self) {
82 let _ = R1::core_idemp;
83 let _ = R2::core_idemp;
84 }
85
86 #[logic]
87 #[requires(i.op(i) == Some(i))]
88 #[requires(i.op(self) == Some(self))]
89 #[ensures(match self.core() {
90 Some(c) => i.incl(c),
91 None => false,
92 })]
93 fn core_is_maximal_idemp(self, i: Self) {
94 match (self, i) {
95 (Sum::Left(s), Sum::Left(i)) => s.core_is_maximal_idemp(i),
96 (Sum::Right(s), Sum::Right(i)) => s.core_is_maximal_idemp(i),
97 _ => (),
98 }
99 }
100
101 #[logic(open)]
102 #[ensures(result == (forall<x, y> self.op(x) != None ==>
103 self.op(x) == self.op(y) ==> x == y))]
104 fn cancelable(self) -> bool {
105 match self {
106 Self::Left(l) => l.cancelable(),
107 Self::Right(r) => r.cancelable(),
108 }
109 }
110}
111
112pub struct SumUpdateL<U>(pub U);
134
135impl<R1: RA, R2: RA, U: Update<R1>> Update<Sum<R1, R2>> for SumUpdateL<U> {
136 type Choice = U::Choice;
137
138 #[logic(open, inline)]
139 fn premise(self, from: Sum<R1, R2>) -> bool {
140 match from {
141 Sum::Left(from) => self.0.premise(from),
142 Sum::Right(_) => false,
143 }
144 }
145
146 #[logic(open, inline)]
147 #[requires(self.premise(from))]
148 fn update(self, from: Sum<R1, R2>, ch: U::Choice) -> Sum<R1, R2> {
149 match from {
150 Sum::Left(from) => Sum::Left(self.0.update(from, ch)),
151 x => x, }
153 }
154
155 #[logic]
156 #[requires(self.premise(from))]
157 #[requires(from.op(frame) != None)]
158 #[ensures(self.update(from, result).op(frame) != None)]
159 fn frame_preserving(self, from: Sum<R1, R2>, frame: Sum<R1, R2>) -> U::Choice {
160 match (from, frame) {
161 (Sum::Left(from), Sum::Left(frame)) => self.0.frame_preserving(from, frame),
162 _ => any(),
163 }
164 }
165}
166
167pub struct SumUpdateR<U>(pub U);
189
190impl<R: RA, U: Update<R>, V: RA> Update<Sum<V, R>> for SumUpdateR<U> {
191 type Choice = U::Choice;
192
193 #[logic(open, inline)]
194 fn premise(self, from: Sum<V, R>) -> bool {
195 match from {
196 Sum::Right(from) => self.0.premise(from),
197 Sum::Left(_) => false,
198 }
199 }
200
201 #[logic(open, inline)]
202 #[requires(self.premise(from))]
203 fn update(self, from: Sum<V, R>, ch: U::Choice) -> Sum<V, R> {
204 match from {
205 Sum::Right(from) => Sum::Right(self.0.update(from, ch)),
206 x => x, }
208 }
209
210 #[logic]
211 #[requires(self.premise(from))]
212 #[requires(from.op(frame) != None)]
213 #[ensures(self.update(from, result).op(frame) != None)]
214 fn frame_preserving(self, from: Sum<V, R>, frame: Sum<V, R>) -> U::Choice {
215 match (from, frame) {
216 (Sum::Right(from), Sum::Right(frame)) => self.0.frame_preserving(from, frame),
217 _ => any(),
218 }
219 }
220}
221
222pub struct SumLocalUpdateL<U>(pub U);
228
229impl<R1: RA, R2: RA, U: LocalUpdate<R1>> LocalUpdate<Sum<R1, R2>> for SumLocalUpdateL<U> {
230 #[logic(open, inline)]
231 fn premise(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> bool {
232 match (from_auth, from_frag) {
233 (Sum::Left(from_auth), Sum::Left(from_frag)) => self.0.premise(from_auth, from_frag),
234 (Sum::Right(_), Sum::Right(_)) => false,
235 _ => true,
236 }
237 }
238
239 #[logic(open, inline)]
240 fn update(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> (Sum<R1, R2>, Sum<R1, R2>) {
241 match (from_auth, from_frag) {
242 (Sum::Left(from_auth), Sum::Left(from_frag)) => {
243 let (to_auth, to_frag) = self.0.update(from_auth, from_frag);
244 (Sum::Left(to_auth), Sum::Left(to_frag))
245 }
246 _ => any(),
247 }
248 }
249
250 #[logic]
251 #[requires(self.premise(from_auth, from_frag))]
252 #[requires(Some(from_frag).op(frame) == Some(Some(from_auth)))]
253 #[ensures({
254 let (to_auth, to_frag) = self.update(from_auth, from_frag);
255 Some(to_frag).op(frame) == Some(Some(to_auth))
256 })]
257 fn frame_preserving(
258 self,
259 from_auth: Sum<R1, R2>,
260 from_frag: Sum<R1, R2>,
261 frame: Option<Sum<R1, R2>>,
262 ) {
263 match (from_auth, from_frag, frame) {
264 (Sum::Left(from_auth), Sum::Left(from_frag), Some(Sum::Left(frame))) => {
265 self.0.frame_preserving(from_auth, from_frag, Some(frame))
266 }
267 (Sum::Left(from_auth), Sum::Left(from_frag), None) => {
268 self.0.frame_preserving(from_auth, from_frag, None)
269 }
270 _ => (),
271 }
272 }
273}
274
275pub struct SumLocalUpdateR<U>(pub U);
281
282impl<R1: RA, R2: RA, U: LocalUpdate<R2>> LocalUpdate<Sum<R1, R2>> for SumLocalUpdateR<U> {
283 #[logic(open, inline)]
284 fn premise(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> bool {
285 match (from_auth, from_frag) {
286 (Sum::Right(from_auth), Sum::Right(from_frag)) => self.0.premise(from_auth, from_frag),
287 (Sum::Left(_), Sum::Left(_)) => false,
288 _ => true,
289 }
290 }
291
292 #[logic(open, inline)]
293 fn update(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> (Sum<R1, R2>, Sum<R1, R2>) {
294 match (from_auth, from_frag) {
295 (Sum::Right(from_auth), Sum::Right(from_frag)) => {
296 let (to_auth, to_frag) = self.0.update(from_auth, from_frag);
297 (Sum::Right(to_auth), Sum::Right(to_frag))
298 }
299 _ => any(),
300 }
301 }
302
303 #[logic]
304 #[requires(self.premise(from_auth, from_frag))]
305 #[requires(Some(from_frag).op(frame) == Some(Some(from_auth)))]
306 #[ensures({
307 let (to_auth, to_frag) = self.update(from_auth, from_frag);
308 Some(to_frag).op(frame) == Some(Some(to_auth))
309 })]
310 fn frame_preserving(
311 self,
312 from_auth: Sum<R1, R2>,
313 from_frag: Sum<R1, R2>,
314 frame: Option<Sum<R1, R2>>,
315 ) {
316 match (from_auth, from_frag, frame) {
317 (Sum::Right(from_auth), Sum::Right(from_frag), Some(Sum::Right(frame))) => {
318 self.0.frame_preserving(from_auth, from_frag, Some(frame))
319 }
320 (Sum::Right(from_auth), Sum::Right(from_frag), None) => {
321 self.0.frame_preserving(from_auth, from_frag, None)
322 }
323 _ => (),
324 }
325 }
326}