1#[cfg(creusot)]
2use crate::logic::such_that;
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(match result {
32 Some(c) => factor.op(c) == Some(self),
33 None => forall<c: Self> factor.op(c) != Some(self),
34 })]
35 fn factor(self, factor: Self) -> Option<Self> {
36 match (self, factor) {
37 (Self::Left(x), Self::Left(y)) => x.factor(y).map_logic(|l| Self::Left(l)),
38 (Self::Right(x), Self::Right(y)) => x.factor(y).map_logic(|r| Self::Right(r)),
39 _ => None,
40 }
41 }
42
43 #[logic(open, inline)]
44 #[ensures(result == (self == other))]
45 fn eq(self, other: Self) -> bool {
46 match (self, other) {
47 (Sum::Left(s), Sum::Left(o)) => s.eq(o),
48 (Sum::Right(s), Sum::Right(o)) => s.eq(o),
49 _ => false,
50 }
51 }
52
53 #[logic(law)]
54 #[ensures(a.op(b) == b.op(a))]
55 fn commutative(a: Self, b: Self) {}
56
57 #[logic]
58 #[ensures(a.op(b).and_then_logic(|ab: Self| ab.op(c)) == b.op(c).and_then_logic(|bc| a.op(bc)))]
59 fn associative(a: Self, b: Self, c: Self) {}
60
61 #[logic(open)]
62 fn core(self) -> Option<Self> {
63 match self {
64 Self::Left(x) => x.core().map_logic(|l| Self::Left(l)),
65 Self::Right(x) => x.core().map_logic(|r| Self::Right(r)),
66 }
67 }
68
69 #[logic]
70 #[requires(self.core() != None)]
71 #[ensures({
72 let c = self.core().unwrap_logic();
73 c.op(c) == Some(c)
74 })]
75 #[ensures(self.core().unwrap_logic().op(self) == Some(self))]
76 fn core_idemp(self) {
77 let _ = R1::core_idemp;
78 let _ = R2::core_idemp;
79 }
80
81 #[logic]
82 #[requires(i.op(i) == Some(i))]
83 #[requires(i.op(self) == Some(self))]
84 #[ensures(match self.core() {
85 Some(c) => i.incl(c),
86 None => false,
87 })]
88 fn core_is_maximal_idemp(self, i: Self) {
89 match (self, i) {
90 (Sum::Left(s), Sum::Left(i)) => s.core_is_maximal_idemp(i),
91 (Sum::Right(s), Sum::Right(i)) => s.core_is_maximal_idemp(i),
92 _ => (),
93 }
94 }
95}
96
97pub struct SumUpdateL<U>(pub U);
119
120impl<R1: RA, R2: RA, U: Update<R1>> Update<Sum<R1, R2>> for SumUpdateL<U> {
121 type Choice = U::Choice;
122
123 #[logic(open, inline)]
124 fn premise(self, from: Sum<R1, R2>) -> bool {
125 match from {
126 Sum::Left(from) => self.0.premise(from),
127 Sum::Right(_) => false,
128 }
129 }
130
131 #[logic(open, inline)]
132 #[requires(self.premise(from))]
133 fn update(self, from: Sum<R1, R2>, ch: U::Choice) -> Sum<R1, R2> {
134 match from {
135 Sum::Left(from) => Sum::Left(self.0.update(from, ch)),
136 x => x, }
138 }
139
140 #[logic]
141 #[requires(self.premise(from))]
142 #[requires(from.op(frame) != None)]
143 #[ensures(self.update(from, result).op(frame) != None)]
144 fn frame_preserving(self, from: Sum<R1, R2>, frame: Sum<R1, R2>) -> U::Choice {
145 match (from, frame) {
146 (Sum::Left(from), Sum::Left(frame)) => self.0.frame_preserving(from, frame),
147 _ => such_that(|_| true),
148 }
149 }
150}
151
152pub struct SumUpdateR<U>(pub U);
174
175impl<R: RA, U: Update<R>, V: RA> Update<Sum<V, R>> for SumUpdateR<U> {
176 type Choice = U::Choice;
177
178 #[logic(open, inline)]
179 fn premise(self, from: Sum<V, R>) -> bool {
180 match from {
181 Sum::Right(from) => self.0.premise(from),
182 Sum::Left(_) => false,
183 }
184 }
185
186 #[logic(open, inline)]
187 #[requires(self.premise(from))]
188 fn update(self, from: Sum<V, R>, ch: U::Choice) -> Sum<V, R> {
189 match from {
190 Sum::Right(from) => Sum::Right(self.0.update(from, ch)),
191 x => x, }
193 }
194
195 #[logic]
196 #[requires(self.premise(from))]
197 #[requires(from.op(frame) != None)]
198 #[ensures(self.update(from, result).op(frame) != None)]
199 fn frame_preserving(self, from: Sum<V, R>, frame: Sum<V, R>) -> U::Choice {
200 match (from, frame) {
201 (Sum::Right(from), Sum::Right(frame)) => self.0.frame_preserving(from, frame),
202 _ => such_that(|_| true),
203 }
204 }
205}
206
207pub struct SumLocalUpdateL<U>(pub U);
213
214impl<R1: RA, R2: RA, U: LocalUpdate<R1>> LocalUpdate<Sum<R1, R2>> for SumLocalUpdateL<U> {
215 #[logic(open, inline)]
216 fn premise(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> bool {
217 match (from_auth, from_frag) {
218 (Sum::Left(from_auth), Sum::Left(from_frag)) => self.0.premise(from_auth, from_frag),
219 (Sum::Right(_), Sum::Right(_)) => false,
220 _ => true,
221 }
222 }
223
224 #[logic(open, inline)]
225 fn update(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> (Sum<R1, R2>, Sum<R1, R2>) {
226 match (from_auth, from_frag) {
227 (Sum::Left(from_auth), Sum::Left(from_frag)) => {
228 let (to_auth, to_frag) = self.0.update(from_auth, from_frag);
229 (Sum::Left(to_auth), Sum::Left(to_frag))
230 }
231 _ => such_that(|_| true),
232 }
233 }
234
235 #[logic]
236 #[requires(self.premise(from_auth, from_frag))]
237 #[requires(Some(from_frag).op(frame) == Some(Some(from_auth)))]
238 #[ensures({
239 let (to_auth, to_frag) = self.update(from_auth, from_frag);
240 Some(to_frag).op(frame) == Some(Some(to_auth))
241 })]
242 fn frame_preserving(
243 self,
244 from_auth: Sum<R1, R2>,
245 from_frag: Sum<R1, R2>,
246 frame: Option<Sum<R1, R2>>,
247 ) {
248 match (from_auth, from_frag, frame) {
249 (Sum::Left(from_auth), Sum::Left(from_frag), Some(Sum::Left(frame))) => {
250 self.0.frame_preserving(from_auth, from_frag, Some(frame))
251 }
252 (Sum::Left(from_auth), Sum::Left(from_frag), None) => {
253 self.0.frame_preserving(from_auth, from_frag, None)
254 }
255 _ => (),
256 }
257 }
258}
259
260pub struct SumLocalUpdateR<U>(pub U);
266
267impl<R1: RA, R2: RA, U: LocalUpdate<R2>> LocalUpdate<Sum<R1, R2>> for SumLocalUpdateR<U> {
268 #[logic(open, inline)]
269 fn premise(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> bool {
270 match (from_auth, from_frag) {
271 (Sum::Right(from_auth), Sum::Right(from_frag)) => self.0.premise(from_auth, from_frag),
272 (Sum::Left(_), Sum::Left(_)) => false,
273 _ => true,
274 }
275 }
276
277 #[logic(open, inline)]
278 fn update(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> (Sum<R1, R2>, Sum<R1, R2>) {
279 match (from_auth, from_frag) {
280 (Sum::Right(from_auth), Sum::Right(from_frag)) => {
281 let (to_auth, to_frag) = self.0.update(from_auth, from_frag);
282 (Sum::Right(to_auth), Sum::Right(to_frag))
283 }
284 _ => such_that(|_| true),
285 }
286 }
287
288 #[logic]
289 #[requires(self.premise(from_auth, from_frag))]
290 #[requires(Some(from_frag).op(frame) == Some(Some(from_auth)))]
291 #[ensures({
292 let (to_auth, to_frag) = self.update(from_auth, from_frag);
293 Some(to_frag).op(frame) == Some(Some(to_auth))
294 })]
295 fn frame_preserving(
296 self,
297 from_auth: Sum<R1, R2>,
298 from_frag: Sum<R1, R2>,
299 frame: Option<Sum<R1, R2>>,
300 ) {
301 match (from_auth, from_frag, frame) {
302 (Sum::Right(from_auth), Sum::Right(from_frag), Some(Sum::Right(frame))) => {
303 self.0.frame_preserving(from_auth, from_frag, Some(frame))
304 }
305 (Sum::Right(from_auth), Sum::Right(from_frag), None) => {
306 self.0.frame_preserving(from_auth, from_frag, None)
307 }
308 _ => (),
309 }
310 }
311}