1#[cfg(creusot)]
2use crate::logic::any;
3use crate::{
4 logic::ra::{
5 RA, UnitRA,
6 update::{LocalUpdate, Update},
7 },
8 prelude::*,
9};
10
11impl<T: RA> RA for Option<T> {
12 #[logic(open)]
13 fn op(self, other: Self) -> Option<Self> {
14 match (self, other) {
15 (None, _) => Some(other),
16 (_, None) => Some(self),
17 (Some(x), Some(y)) => x.op(y).map_logic(|z| Some(z)),
18 }
19 }
20
21 #[logic(open)]
22 #[ensures(result == (exists<factor> self.op(factor) == Some(other)))]
23 fn incl(self, other: Self) -> bool {
24 match (self, other) {
25 (None, _) => true,
26 (_, None) => false,
27 (Some(x), Some(y)) => {
28 proof_assert!(forall<f> x.op(f) == Some(y) ==> self.op(Some(f)) == Some(other));
29 x.incl_eq(y)
30 }
31 }
32 }
33
34 #[logic(open, inline)]
35 #[ensures(#[trigger(self == other)] result == (self == other))]
36 fn eq(self, other: Self) -> bool {
37 match (self, other) {
38 (Some(s), Some(o)) => s.eq(o),
39 (None, None) => true,
40 _ => false,
41 }
42 }
43
44 #[logic(law)]
45 #[ensures(a.op(b) == b.op(a))]
46 fn commutative(a: Self, b: Self) {
47 let _ = <T as RA>::commutative;
48 }
49
50 #[logic]
51 #[ensures(a.op(b).and_then_logic(|ab: Self| ab.op(c)) == b.op(c).and_then_logic(|bc| a.op(bc)))]
52 fn associative(a: Self, b: Self, c: Self) {}
53
54 #[logic(open)]
55 fn core(self) -> Option<Self> {
56 match self {
57 None => Some(None),
58 Some(x) => Some(x.core()),
59 }
60 }
61
62 #[logic]
63 #[requires(self.core() != None)]
64 #[ensures({
65 let c = self.core().unwrap_logic();
66 c.op(c) == Some(c)
67 })]
68 #[ensures(self.core().unwrap_logic().op(self) == Some(self))]
69 fn core_idemp(self) {
70 self.core_total_idemp()
71 }
72
73 #[logic]
74 #[requires(i.op(i) == Some(i))]
75 #[requires(i.op(self) == Some(self))]
76 #[ensures(match self.core() {
77 Some(c) => i.incl(c),
78 None => false,
79 })]
80 fn core_is_maximal_idemp(self, i: Self) {
81 match (self, i) {
82 (Some(x), Some(i)) => x.core_is_maximal_idemp(i),
83 _ => (),
84 }
85 }
86
87 #[logic(open)]
88 #[ensures(result == (forall<x, y> self.op(x) != None ==>
89 self.op(x) == self.op(y) ==> x == y))]
90 fn cancelable(self) -> bool {
91 match self {
92 None => true,
93 Some(this) => {
94 let _ = T::core_is_maximal_idemp;
95 let _ = T::core_idemp;
96 proof_assert! {
97 this.cancelable() ==>
98 forall<x> this.op(x) == Some(this) ==> x.op(x) == Some(x)
99 };
100 proof_assert! {
101 match this.core() {
102 None => true,
103 Some(c) => self.op(None) == self.op(Some(c))
104 }
105 };
106 this.cancelable() && this.core() == None
107 }
108 }
109 }
110}
111
112impl<T: RA> UnitRA for Option<T> {
113 #[logic(open)]
114 #[ensures(forall<x: Self> #[trigger(x.op(result))] x.op(result) == Some(x))]
115 fn unit() -> Self {
116 None
117 }
118
119 #[logic(open)]
120 #[ensures(self.core() == Some(result))]
121 fn core_total(self) -> Self {
122 match self {
123 None => None,
124 Some(x) => x.core(),
125 }
126 }
127
128 #[logic]
129 #[ensures(self.core_total().op(self.core_total()) == Some(self.core_total()))]
130 #[ensures(self.core_total().op(self) == Some(self))]
131 fn core_total_idemp(self) {
132 let _ = T::core_idemp;
133 }
134}
135
136pub struct OptionUpdate<U>(pub U);
157
158impl<R: RA, U: Update<R>> Update<Option<R>> for OptionUpdate<U> {
159 type Choice = U::Choice;
160
161 #[logic(open, inline)]
162 fn premise(self, from: Option<R>) -> bool {
163 match from {
164 Some(from) => self.0.premise(from),
165 None => false,
166 }
167 }
168
169 #[logic(open, inline)]
170 #[requires(self.premise(from))]
171 fn update(self, from: Option<R>, ch: U::Choice) -> Option<R> {
172 match from {
173 Some(from) => Some(self.0.update(from, ch)),
174 None => None, }
176 }
177
178 #[logic]
179 #[requires(self.premise(from))]
180 #[requires(from.op(frame) != None)]
181 #[ensures(self.update(from, result).op(frame) != None)]
182 fn frame_preserving(self, from: Option<R>, frame: Option<R>) -> U::Choice {
183 match frame {
184 Some(frame) => self.0.frame_preserving(from.unwrap_logic(), frame),
185 None => any(),
186 }
187 }
188}
189
190pub struct OptionLocalUpdate<U>(pub U);
195
196impl<R: RA, U: LocalUpdate<R>> LocalUpdate<Option<R>> for OptionLocalUpdate<U> {
197 #[logic(open, inline)]
198 fn premise(self, from_auth: Option<R>, from_frag: Option<R>) -> bool {
199 match (from_auth, from_frag) {
200 (Some(from_auth), Some(from_frag)) => self.0.premise(from_auth, from_frag),
201 _ => false,
202 }
203 }
204
205 #[logic(open, inline)]
206 fn update(self, from_auth: Option<R>, from_frag: Option<R>) -> (Option<R>, Option<R>) {
207 match (from_auth, from_frag) {
208 (Some(from_auth), Some(from_frag)) => {
209 let (to_auth, to_frag) = self.0.update(from_auth, from_frag);
210 (Some(to_auth), Some(to_frag))
211 }
212 _ => (None, None), }
214 }
215
216 #[logic]
217 #[requires(self.premise(from_auth, from_frag))]
218 #[requires(Some(from_frag).op(frame) == Some(Some(from_auth)))]
219 #[ensures({
220 let (to_auth, to_frag) = self.update(from_auth, from_frag);
221 Some(to_frag).op(frame) == Some(Some(to_auth))
222 })]
223 fn frame_preserving(
224 self,
225 from_auth: Option<R>,
226 from_frag: Option<R>,
227 frame: Option<Option<R>>,
228 ) {
229 let frame = match frame {
230 None => None,
231 Some(f) => f,
232 };
233 self.0.frame_preserving(from_auth.unwrap_logic(), from_frag.unwrap_logic(), frame)
234 }
235}