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) => {
107 proof_assert!(forall<b, c> l.op(b) == l.op(c) ==>
108 self.op(Self::Left(b)) == self.op(Self::Left(c)));
109 l.cancelable()
110 }
111 Self::Right(r) => {
112 proof_assert!(forall<b, c> r.op(b) == r.op(c) ==>
113 self.op(Self::Right(b)) == self.op(Self::Right(c)));
114 r.cancelable()
115 }
116 }
117 }
118}
119
120pub struct SumUpdateL<U>(pub U);
142
143impl<R1: RA, R2: RA, U: Update<R1>> Update<Sum<R1, R2>> for SumUpdateL<U> {
144 type Choice = U::Choice;
145
146 #[logic(open, inline)]
147 fn premise(self, from: Sum<R1, R2>) -> bool {
148 match from {
149 Sum::Left(from) => self.0.premise(from),
150 Sum::Right(_) => false,
151 }
152 }
153
154 #[logic(open, inline)]
155 #[requires(self.premise(from))]
156 fn update(self, from: Sum<R1, R2>, ch: U::Choice) -> Sum<R1, R2> {
157 match from {
158 Sum::Left(from) => Sum::Left(self.0.update(from, ch)),
159 x => x, }
161 }
162
163 #[logic]
164 #[requires(self.premise(from))]
165 #[requires(from.op(frame) != None)]
166 #[ensures(self.update(from, result).op(frame) != None)]
167 fn frame_preserving(self, from: Sum<R1, R2>, frame: Sum<R1, R2>) -> U::Choice {
168 match (from, frame) {
169 (Sum::Left(from), Sum::Left(frame)) => self.0.frame_preserving(from, frame),
170 _ => any(),
171 }
172 }
173}
174
175pub struct SumUpdateR<U>(pub U);
197
198impl<R: RA, U: Update<R>, V: RA> Update<Sum<V, R>> for SumUpdateR<U> {
199 type Choice = U::Choice;
200
201 #[logic(open, inline)]
202 fn premise(self, from: Sum<V, R>) -> bool {
203 match from {
204 Sum::Right(from) => self.0.premise(from),
205 Sum::Left(_) => false,
206 }
207 }
208
209 #[logic(open, inline)]
210 #[requires(self.premise(from))]
211 fn update(self, from: Sum<V, R>, ch: U::Choice) -> Sum<V, R> {
212 match from {
213 Sum::Right(from) => Sum::Right(self.0.update(from, ch)),
214 x => x, }
216 }
217
218 #[logic]
219 #[requires(self.premise(from))]
220 #[requires(from.op(frame) != None)]
221 #[ensures(self.update(from, result).op(frame) != None)]
222 fn frame_preserving(self, from: Sum<V, R>, frame: Sum<V, R>) -> U::Choice {
223 match (from, frame) {
224 (Sum::Right(from), Sum::Right(frame)) => self.0.frame_preserving(from, frame),
225 _ => any(),
226 }
227 }
228}
229
230pub struct SumLocalUpdateL<U>(pub U);
236
237impl<R1: RA, R2: RA, U: LocalUpdate<R1>> LocalUpdate<Sum<R1, R2>> for SumLocalUpdateL<U> {
238 #[logic(open, inline)]
239 fn premise(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> bool {
240 match (from_auth, from_frag) {
241 (Sum::Left(from_auth), Sum::Left(from_frag)) => self.0.premise(from_auth, from_frag),
242 (Sum::Right(_), Sum::Right(_)) => false,
243 _ => true,
244 }
245 }
246
247 #[logic(open, inline)]
248 fn update(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> (Sum<R1, R2>, Sum<R1, R2>) {
249 match (from_auth, from_frag) {
250 (Sum::Left(from_auth), Sum::Left(from_frag)) => {
251 let (to_auth, to_frag) = self.0.update(from_auth, from_frag);
252 (Sum::Left(to_auth), Sum::Left(to_frag))
253 }
254 _ => any(),
255 }
256 }
257
258 #[logic]
259 #[requires(self.premise(from_auth, from_frag))]
260 #[requires(Some(from_frag).op(frame) == Some(Some(from_auth)))]
261 #[ensures({
262 let (to_auth, to_frag) = self.update(from_auth, from_frag);
263 Some(to_frag).op(frame) == Some(Some(to_auth))
264 })]
265 fn frame_preserving(
266 self,
267 from_auth: Sum<R1, R2>,
268 from_frag: Sum<R1, R2>,
269 frame: Option<Sum<R1, R2>>,
270 ) {
271 match (from_auth, from_frag, frame) {
272 (Sum::Left(from_auth), Sum::Left(from_frag), Some(Sum::Left(frame))) => {
273 self.0.frame_preserving(from_auth, from_frag, Some(frame))
274 }
275 (Sum::Left(from_auth), Sum::Left(from_frag), None) => {
276 self.0.frame_preserving(from_auth, from_frag, None)
277 }
278 _ => (),
279 }
280 }
281}
282
283pub struct SumLocalUpdateR<U>(pub U);
289
290impl<R1: RA, R2: RA, U: LocalUpdate<R2>> LocalUpdate<Sum<R1, R2>> for SumLocalUpdateR<U> {
291 #[logic(open, inline)]
292 fn premise(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> bool {
293 match (from_auth, from_frag) {
294 (Sum::Right(from_auth), Sum::Right(from_frag)) => self.0.premise(from_auth, from_frag),
295 (Sum::Left(_), Sum::Left(_)) => false,
296 _ => true,
297 }
298 }
299
300 #[logic(open, inline)]
301 fn update(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> (Sum<R1, R2>, Sum<R1, R2>) {
302 match (from_auth, from_frag) {
303 (Sum::Right(from_auth), Sum::Right(from_frag)) => {
304 let (to_auth, to_frag) = self.0.update(from_auth, from_frag);
305 (Sum::Right(to_auth), Sum::Right(to_frag))
306 }
307 _ => any(),
308 }
309 }
310
311 #[logic]
312 #[requires(self.premise(from_auth, from_frag))]
313 #[requires(Some(from_frag).op(frame) == Some(Some(from_auth)))]
314 #[ensures({
315 let (to_auth, to_frag) = self.update(from_auth, from_frag);
316 Some(to_frag).op(frame) == Some(Some(to_auth))
317 })]
318 fn frame_preserving(
319 self,
320 from_auth: Sum<R1, R2>,
321 from_frag: Sum<R1, R2>,
322 frame: Option<Sum<R1, R2>>,
323 ) {
324 match (from_auth, from_frag, frame) {
325 (Sum::Right(from_auth), Sum::Right(from_frag), Some(Sum::Right(frame))) => {
326 self.0.frame_preserving(from_auth, from_frag, Some(frame))
327 }
328 (Sum::Right(from_auth), Sum::Right(from_frag), None) => {
329 self.0.frame_preserving(from_auth, from_frag, None)
330 }
331 _ => (),
332 }
333 }
334}