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);
98
99impl<R1: RA, R2: RA, U: Update<R1>> Update<Sum<R1, R2>> for SumUpdateL<U> {
100 type Choice = U::Choice;
101
102 #[logic(open, inline)]
103 fn premise(self, from: Sum<R1, R2>) -> bool {
104 match from {
105 Sum::Left(from) => self.0.premise(from),
106 Sum::Right(_) => false,
107 }
108 }
109
110 #[logic(open, inline)]
111 #[requires(self.premise(from))]
112 fn update(self, from: Sum<R1, R2>, ch: U::Choice) -> Sum<R1, R2> {
113 match from {
114 Sum::Left(from) => Sum::Left(self.0.update(from, ch)),
115 x => x, }
117 }
118
119 #[logic]
120 #[requires(self.premise(from))]
121 #[requires(from.op(frame) != None)]
122 #[ensures(self.update(from, result).op(frame) != None)]
123 fn frame_preserving(self, from: Sum<R1, R2>, frame: Sum<R1, R2>) -> U::Choice {
124 match (from, frame) {
125 (Sum::Left(from), Sum::Left(frame)) => self.0.frame_preserving(from, frame),
126 _ => such_that(|_| true),
127 }
128 }
129}
130
131pub struct SumUpdateR<U>(pub U);
132
133impl<R: RA, U: Update<R>, V: RA> Update<Sum<V, R>> for SumUpdateR<U> {
134 type Choice = U::Choice;
135
136 #[logic(open, inline)]
137 fn premise(self, from: Sum<V, R>) -> bool {
138 match from {
139 Sum::Right(from) => self.0.premise(from),
140 Sum::Left(_) => false,
141 }
142 }
143
144 #[logic(open, inline)]
145 #[requires(self.premise(from))]
146 fn update(self, from: Sum<V, R>, ch: U::Choice) -> Sum<V, R> {
147 match from {
148 Sum::Right(from) => Sum::Right(self.0.update(from, ch)),
149 x => x, }
151 }
152
153 #[logic]
154 #[requires(self.premise(from))]
155 #[requires(from.op(frame) != None)]
156 #[ensures(self.update(from, result).op(frame) != None)]
157 fn frame_preserving(self, from: Sum<V, R>, frame: Sum<V, R>) -> U::Choice {
158 match (from, frame) {
159 (Sum::Right(from), Sum::Right(frame)) => self.0.frame_preserving(from, frame),
160 _ => such_that(|_| true),
161 }
162 }
163}
164
165pub struct SumLocalUpdateL<U>(pub U);
166
167impl<R1: RA, R2: RA, U: LocalUpdate<R1>> LocalUpdate<Sum<R1, R2>> for SumLocalUpdateL<U> {
168 #[logic(open, inline)]
169 fn premise(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> bool {
170 match (from_auth, from_frag) {
171 (Sum::Left(from_auth), Sum::Left(from_frag)) => self.0.premise(from_auth, from_frag),
172 (Sum::Right(_), Sum::Right(_)) => false,
173 _ => true,
174 }
175 }
176
177 #[logic(open, inline)]
178 fn update(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> (Sum<R1, R2>, Sum<R1, R2>) {
179 match (from_auth, from_frag) {
180 (Sum::Left(from_auth), Sum::Left(from_frag)) => {
181 let (to_auth, to_frag) = self.0.update(from_auth, from_frag);
182 (Sum::Left(to_auth), Sum::Left(to_frag))
183 }
184 _ => such_that(|_| true),
185 }
186 }
187
188 #[logic]
189 #[requires(self.premise(from_auth, from_frag))]
190 #[requires(Some(from_frag).op(frame) == Some(Some(from_auth)))]
191 #[ensures({
192 let (to_auth, to_frag) = self.update(from_auth, from_frag);
193 Some(to_frag).op(frame) == Some(Some(to_auth))
194 })]
195 fn frame_preserving(
196 self,
197 from_auth: Sum<R1, R2>,
198 from_frag: Sum<R1, R2>,
199 frame: Option<Sum<R1, R2>>,
200 ) {
201 match (from_auth, from_frag, frame) {
202 (Sum::Left(from_auth), Sum::Left(from_frag), Some(Sum::Left(frame))) => {
203 self.0.frame_preserving(from_auth, from_frag, Some(frame))
204 }
205 (Sum::Left(from_auth), Sum::Left(from_frag), None) => {
206 self.0.frame_preserving(from_auth, from_frag, None)
207 }
208 _ => (),
209 }
210 }
211}
212
213pub struct SumLocalUpdateR<U>(pub U);
214
215impl<R1: RA, R2: RA, U: LocalUpdate<R2>> LocalUpdate<Sum<R1, R2>> for SumLocalUpdateR<U> {
216 #[logic(open, inline)]
217 fn premise(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> bool {
218 match (from_auth, from_frag) {
219 (Sum::Right(from_auth), Sum::Right(from_frag)) => self.0.premise(from_auth, from_frag),
220 (Sum::Left(_), Sum::Left(_)) => false,
221 _ => true,
222 }
223 }
224
225 #[logic(open, inline)]
226 fn update(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> (Sum<R1, R2>, Sum<R1, R2>) {
227 match (from_auth, from_frag) {
228 (Sum::Right(from_auth), Sum::Right(from_frag)) => {
229 let (to_auth, to_frag) = self.0.update(from_auth, from_frag);
230 (Sum::Right(to_auth), Sum::Right(to_frag))
231 }
232 _ => such_that(|_| true),
233 }
234 }
235
236 #[logic]
237 #[requires(self.premise(from_auth, from_frag))]
238 #[requires(Some(from_frag).op(frame) == Some(Some(from_auth)))]
239 #[ensures({
240 let (to_auth, to_frag) = self.update(from_auth, from_frag);
241 Some(to_frag).op(frame) == Some(Some(to_auth))
242 })]
243 fn frame_preserving(
244 self,
245 from_auth: Sum<R1, R2>,
246 from_frag: Sum<R1, R2>,
247 frame: Option<Sum<R1, R2>>,
248 ) {
249 match (from_auth, from_frag, frame) {
250 (Sum::Right(from_auth), Sum::Right(from_frag), Some(Sum::Right(frame))) => {
251 self.0.frame_preserving(from_auth, from_frag, Some(frame))
252 }
253 (Sum::Right(from_auth), Sum::Right(from_frag), None) => {
254 self.0.frame_preserving(from_auth, from_frag, None)
255 }
256 _ => (),
257 }
258 }
259}