1use crate::prelude::*;
4use core::cmp::Ordering;
5
6pub trait PartialOrdLogic {
15 #[logic]
17 fn lt_log(self, other: Self) -> bool;
18
19 #[logic(open, inline, sealed)]
21 fn gt_log(self, other: Self) -> bool {
22 other < self
23 }
24
25 #[logic(open, inline)]
27 fn le_log(self, other: Self) -> bool {
28 pearlite! { self < other || self == other }
29 }
30
31 #[logic(open, inline, sealed)]
33 fn ge_log(self, other: Self) -> bool {
34 other <= self
35 }
36
37 #[logic(law)]
38 #[ensures(!(self < self))]
39 fn irreflexive(self);
40
41 #[logic(law)]
42 #[requires(x < y)]
43 #[requires(y < z)]
44 #[ensures(x < z)]
45 fn transitive(x: Self, y: Self, z: Self);
46
47 #[logic(law)]
48 #[ensures((self <= other) == (self < other || self == other))]
49 fn le_lt_log(self, other: Self);
50
51 #[logic(open, sealed)]
52 fn partial_cmp_log(self, other: Self) -> Option<Ordering> {
53 if self == other {
54 Some(Ordering::Equal)
55 } else if self < other {
56 Some(Ordering::Less)
57 } else if other < self {
58 Some(Ordering::Greater)
59 } else {
60 None
61 }
62 }
63}
64
65#[allow(unused)]
67pub trait OrdLogic: PartialOrdLogic {
68 #[logic(law)]
70 #[ensures(self < other || self == other || other < self)]
71 fn lt_log_total(self, other: Self);
72
73 #[logic(open, sealed)]
75 fn cmp_log(self, other: Self) -> Ordering {
76 if self == other {
77 Ordering::Equal
78 } else if self < other {
79 Ordering::Less
80 } else {
81 Ordering::Greater
82 }
83 }
84}
85
86#[macro_export]
138macro_rules! partial_ord_laws_impl {
139 ( $($lemma:stmt)* ) => {
140 #[::creusot_std::macros::logic(law)]
141 #[::creusot_std::macros::ensures(!(self < self))]
142 fn irreflexive(self) {
143 $($lemma)*
144 }
145
146 #[::creusot_std::macros::logic(law)]
147 #[::creusot_std::macros::requires(x < y)]
148 #[::creusot_std::macros::requires(y < z)]
149 #[::creusot_std::macros::ensures(x < z)]
150 fn transitive(x: Self, y: Self, z: Self) {
151 $($lemma)*
152 }
153
154 #[::creusot_std::macros::logic(law)]
155 #[::creusot_std::macros::ensures((self <= other) == (self < other || self == other))]
156 fn le_lt_log(self, other: Self) {
157 $($lemma)*
158 }
159 };
160}
161
162pub use partial_ord_laws_impl;
163
164impl<T: PartialOrdLogic> PartialOrdLogic for &T {
165 #[logic(open, inline)]
166 fn lt_log(self, other: Self) -> bool {
167 *self < *other
168 }
169
170 #[logic(open, inline)]
171 fn le_log(self, other: Self) -> bool {
172 *self <= *other
173 }
174
175 partial_ord_laws_impl! {}
176}
177
178impl<T: OrdLogic> OrdLogic for &T {
179 #[logic]
180 #[ensures(self < other || self == other || other < self)]
181 fn lt_log_total(self, other: Self) {
182 let _ = T::lt_log_total;
183 }
184}
185
186impl PartialOrdLogic for Int {
187 #[logic]
188 #[builtin("int.Int.(<=)")]
189 fn le_log(self, _: Self) -> bool {
190 dead
191 }
192
193 #[logic]
194 #[builtin("int.Int.(<)")]
195 fn lt_log(self, _: Self) -> bool {
196 dead
197 }
198
199 #[logic]
200 #[ensures(!(self < self))]
201 fn irreflexive(self) {}
202
203 #[logic]
204 #[requires(x < y)]
205 #[requires(y < z)]
206 #[ensures(x < z)]
207 fn transitive(x: Self, y: Self, z: Self) {}
208
209 #[logic]
210 #[ensures((self <= other) == (self < other || self == other))]
211 fn le_lt_log(self, other: Self) {}
212}
213
214impl OrdLogic for Int {
215 #[logic]
216 #[ensures(self < other || self == other || other < self)]
217 fn lt_log_total(self, other: Self) {}
218}
219
220macro_rules! ord_logic_impl {
221 ($t:ty, $module:literal) => {
222 impl PartialOrdLogic for $t {
223 #[logic]
224 #[builtin(concat!($module, ".le"))]
225 fn le_log(self, _: Self) -> bool {
226 dead
227 }
228
229 #[logic]
230 #[builtin(concat!($module, ".lt"))]
231 fn lt_log(self, _: Self) -> bool {
232 dead
233 }
234
235 #[logic]
236 #[ensures(!(self < self))]
237 fn irreflexive(self) {}
238
239 #[logic]
240 #[requires(x < y)]
241 #[requires(y < z)]
242 #[ensures(x < z)]
243 fn transitive(x: Self, y: Self, z: Self) {}
244
245 #[logic]
246 #[ensures((self <= other) == (self < other || self == other))]
247 fn le_lt_log(self, other: Self) {}
248 }
249
250 impl OrdLogic for $t {
251 #[logic]
252 #[ensures(self < other || self == other || other < self)]
253 fn lt_log_total(self, other: Self) {}
254 }
255 };
256}
257
258impl PartialOrdLogic for f32 {
259 #[logic]
262 #[builtin("creusot.float.Float32.lt")]
263 fn lt_log(self, _: Self) -> bool {
264 dead
265 }
266
267 #[logic]
268 #[ensures(!(self < self))]
269 fn irreflexive(self) {}
270
271 #[logic]
272 #[requires(x < y)]
273 #[requires(y < z)]
274 #[ensures(x < z)]
275 fn transitive(x: Self, y: Self, z: Self) {}
276
277 #[logic]
278 #[ensures((self <= other) == (self < other || self == other))]
279 fn le_lt_log(self, other: Self) {}
280}
281
282impl PartialOrdLogic for f64 {
283 #[logic]
286 #[builtin("creusot.float.Float64.lt")]
287 fn lt_log(self, _: Self) -> bool {
288 dead
289 }
290
291 #[logic]
292 #[ensures(!(self < self))]
293 fn irreflexive(self) {}
294
295 #[logic]
296 #[requires(x < y)]
297 #[requires(y < z)]
298 #[ensures(x < z)]
299 fn transitive(x: Self, y: Self, z: Self) {}
300
301 #[logic]
302 #[ensures((self <= other) == (self < other || self == other))]
303 fn le_lt_log(self, other: Self) {}
304}
305
306ord_logic_impl!(u8, "creusot.int.UInt8$BW$");
307ord_logic_impl!(u16, "creusot.int.UInt16$BW$");
308ord_logic_impl!(u32, "creusot.int.UInt32$BW$");
309ord_logic_impl!(u64, "creusot.int.UInt64$BW$");
310ord_logic_impl!(u128, "creusot.int.UInt128$BW$");
311#[cfg(target_pointer_width = "64")]
312ord_logic_impl!(usize, "creusot.int.UInt64$BW$");
313#[cfg(target_pointer_width = "32")]
314ord_logic_impl!(usize, "creusot.int.UInt32$BW$");
315#[cfg(target_pointer_width = "16")]
316ord_logic_impl!(usize, "creusot.int.UInt16$BW$");
317
318ord_logic_impl!(i8, "creusot.int.Int8$BW$");
319ord_logic_impl!(i16, "creusot.int.Int16$BW$");
320ord_logic_impl!(i32, "creusot.int.Int32$BW$");
321ord_logic_impl!(i64, "creusot.int.Int64$BW$");
322ord_logic_impl!(i128, "creusot.int.Int128$BW$");
323#[cfg(target_pointer_width = "64")]
324ord_logic_impl!(isize, "creusot.int.Int64$BW$");
325#[cfg(target_pointer_width = "32")]
326ord_logic_impl!(isize, "creusot.int.Int32$BW$");
327#[cfg(target_pointer_width = "16")]
328ord_logic_impl!(isize, "creusot.int.Int16$BW$");
329
330ord_logic_impl!(char, "creusot.prelude.Char");
331ord_logic_impl!(bool, "creusot.prelude.Bool");
332
333impl<A: PartialOrdLogic, B: PartialOrdLogic> PartialOrdLogic for (A, B) {
334 #[logic(open)]
335 fn lt_log(self, o: Self) -> bool {
336 self.0 == o.0 && self.1 < o.1 || self.0 < o.0
337 }
338
339 #[logic(open)]
340 fn le_log(self, o: Self) -> bool {
341 self.0 == o.0 && self.1 <= o.1 || self.0 < o.0
342 }
343
344 partial_ord_laws_impl! {}
345}
346
347impl<A: OrdLogic, B: OrdLogic> OrdLogic for (A, B) {
348 #[logic]
349 #[ensures(self < other || self == other || other < self)]
350 fn lt_log_total(self, other: Self) {
351 let _ = A::lt_log_total;
352 let _ = B::lt_log_total;
353 }
354}