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(self), law)]
44 #[ensures(a.op(b) == b.op(a))]
45 fn commutative(a: Self, b: Self) {}
46
47 #[logic(open(self), law)]
48 #[ensures(a.op(b).and_then_logic(|ab: Self| ab.op(c)) == b.op(c).and_then_logic(|bc| a.op(bc)))]
49 fn associative(a: Self, b: Self, c: Self) {}
50
51 #[logic(open)]
52 fn core(self) -> Option<Self> {
53 match self {
54 Self::Left(x) => x.core().map_logic(|l| Self::Left(l)),
55 Self::Right(x) => x.core().map_logic(|r| Self::Right(r)),
56 }
57 }
58
59 #[logic]
60 #[requires(self.core() != None)]
61 #[ensures({
62 let c = self.core().unwrap_logic();
63 c.op(c) == Some(c)
64 })]
65 #[ensures(self.core().unwrap_logic().op(self) == Some(self))]
66 fn core_idemp(self) {
67 let _ = R1::core_idemp;
68 let _ = R2::core_idemp;
69 }
70
71 #[logic]
72 #[requires(i.op(i) == Some(i))]
73 #[requires(i.op(self) == Some(self))]
74 #[ensures(match self.core() {
75 Some(c) => i.incl(c),
76 None => false,
77 })]
78 fn core_is_maximal_idemp(self, i: Self) {
79 match (self, i) {
80 (Sum::Left(s), Sum::Left(i)) => s.core_is_maximal_idemp(i),
81 (Sum::Right(s), Sum::Right(i)) => s.core_is_maximal_idemp(i),
82 _ => (),
83 }
84 }
85}
86
87pub struct SumUpdateL<U>(pub U);
88
89impl<R1: RA, R2: RA, U: Update<R1>> Update<Sum<R1, R2>> for SumUpdateL<U> {
90 type Choice = U::Choice;
91
92 #[logic(open)]
93 fn premise(self, from: Sum<R1, R2>) -> bool {
94 match from {
95 Sum::Left(from) => self.0.premise(from),
96 Sum::Right(_) => false,
97 }
98 }
99
100 #[logic(open)]
101 #[requires(self.premise(from))]
102 fn update(self, from: Sum<R1, R2>, ch: U::Choice) -> Sum<R1, R2> {
103 match from {
104 Sum::Left(from) => Sum::Left(self.0.update(from, ch)),
105 x => x, }
107 }
108
109 #[logic]
110 #[requires(self.premise(from))]
111 #[requires(from.op(frame) != None)]
112 #[ensures(self.update(from, result).op(frame) != None)]
113 fn frame_preserving(self, from: Sum<R1, R2>, frame: Sum<R1, R2>) -> U::Choice {
114 match (from, frame) {
115 (Sum::Left(from), Sum::Left(frame)) => self.0.frame_preserving(from, frame),
116 _ => such_that(|_| true),
117 }
118 }
119}
120
121pub struct SumUpdateR<U>(pub U);
122
123impl<R: RA, U: Update<R>, V: RA> Update<Sum<V, R>> for SumUpdateR<U> {
124 type Choice = U::Choice;
125
126 #[logic(open)]
127 fn premise(self, from: Sum<V, R>) -> bool {
128 match from {
129 Sum::Right(from) => self.0.premise(from),
130 Sum::Left(_) => false,
131 }
132 }
133
134 #[logic(open)]
135 #[requires(self.premise(from))]
136 fn update(self, from: Sum<V, R>, ch: U::Choice) -> Sum<V, R> {
137 match from {
138 Sum::Right(from) => Sum::Right(self.0.update(from, ch)),
139 x => x, }
141 }
142
143 #[logic]
144 #[requires(self.premise(from))]
145 #[requires(from.op(frame) != None)]
146 #[ensures(self.update(from, result).op(frame) != None)]
147 fn frame_preserving(self, from: Sum<V, R>, frame: Sum<V, R>) -> U::Choice {
148 match (from, frame) {
149 (Sum::Right(from), Sum::Right(frame)) => self.0.frame_preserving(from, frame),
150 _ => such_that(|_| true),
151 }
152 }
153}
154
155pub struct SumLocalUpdateL<U>(pub U);
156
157impl<R1: RA, R2: RA, U: LocalUpdate<R1>> LocalUpdate<Sum<R1, R2>> for SumLocalUpdateL<U> {
158 #[logic(open)]
159 fn premise(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> bool {
160 match (from_auth, from_frag) {
161 (Sum::Left(from_auth), Sum::Left(from_frag)) => self.0.premise(from_auth, from_frag),
162 (Sum::Right(_), Sum::Right(_)) => false,
163 _ => true,
164 }
165 }
166
167 #[logic(open)]
168 fn update(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> (Sum<R1, R2>, Sum<R1, R2>) {
169 match (from_auth, from_frag) {
170 (Sum::Left(from_auth), Sum::Left(from_frag)) => {
171 let (to_auth, to_frag) = self.0.update(from_auth, from_frag);
172 (Sum::Left(to_auth), Sum::Left(to_frag))
173 }
174 _ => such_that(|_| true),
175 }
176 }
177
178 #[logic]
179 #[requires(self.premise(from_auth, from_frag))]
180 #[requires(Some(from_frag).op(frame) == Some(Some(from_auth)))]
181 #[ensures({
182 let (to_auth, to_frag) = self.update(from_auth, from_frag);
183 Some(to_frag).op(frame) == Some(Some(to_auth))
184 })]
185 fn frame_preserving(
186 self,
187 from_auth: Sum<R1, R2>,
188 from_frag: Sum<R1, R2>,
189 frame: Option<Sum<R1, R2>>,
190 ) {
191 match (from_auth, from_frag, frame) {
192 (Sum::Left(from_auth), Sum::Left(from_frag), Some(Sum::Left(frame))) => {
193 self.0.frame_preserving(from_auth, from_frag, Some(frame))
194 }
195 (Sum::Left(from_auth), Sum::Left(from_frag), None) => {
196 self.0.frame_preserving(from_auth, from_frag, None)
197 }
198 _ => (),
199 }
200 }
201}
202
203pub struct SumLocalUpdateR<U>(pub U);
204
205impl<R1: RA, R2: RA, U: LocalUpdate<R2>> LocalUpdate<Sum<R1, R2>> for SumLocalUpdateR<U> {
206 #[logic(open)]
207 fn premise(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> bool {
208 match (from_auth, from_frag) {
209 (Sum::Right(from_auth), Sum::Right(from_frag)) => self.0.premise(from_auth, from_frag),
210 (Sum::Left(_), Sum::Left(_)) => false,
211 _ => true,
212 }
213 }
214
215 #[logic(open)]
216 fn update(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> (Sum<R1, R2>, Sum<R1, R2>) {
217 match (from_auth, from_frag) {
218 (Sum::Right(from_auth), Sum::Right(from_frag)) => {
219 let (to_auth, to_frag) = self.0.update(from_auth, from_frag);
220 (Sum::Right(to_auth), Sum::Right(to_frag))
221 }
222 _ => such_that(|_| true),
223 }
224 }
225
226 #[logic]
227 #[requires(self.premise(from_auth, from_frag))]
228 #[requires(Some(from_frag).op(frame) == Some(Some(from_auth)))]
229 #[ensures({
230 let (to_auth, to_frag) = self.update(from_auth, from_frag);
231 Some(to_frag).op(frame) == Some(Some(to_auth))
232 })]
233 fn frame_preserving(
234 self,
235 from_auth: Sum<R1, R2>,
236 from_frag: Sum<R1, R2>,
237 frame: Option<Sum<R1, R2>>,
238 ) {
239 match (from_auth, from_frag, frame) {
240 (Sum::Right(from_auth), Sum::Right(from_frag), Some(Sum::Right(frame))) => {
241 self.0.frame_preserving(from_auth, from_frag, Some(frame))
242 }
243 (Sum::Right(from_auth), Sum::Right(from_frag), None) => {
244 self.0.frame_preserving(from_auth, from_frag, None)
245 }
246 _ => (),
247 }
248 }
249}