1use super::super::prelude::*;
2
3use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
4use core::marker::PointeeSized;
5
6use verus as verus_skip_verusfmt;
7verus_skip_verusfmt! {
8
9#[verifier::external_trait_specification]
10#[verifier::external_trait_extension(PartialEqSpec via PartialEqSpecImpl)]
11pub trait ExPartialEq<Rhs: PointeeSized = Self>: PointeeSized {
12 type ExternalTraitSpecificationFor: PartialEq<Rhs>;
13
14 spec fn obeys_eq_spec() -> bool;
15
16 spec fn eq_spec(&self, other: &Rhs) -> bool;
17
18 fn eq(&self, other: &Rhs) -> (r: bool)
19 ensures
20 Self::obeys_eq_spec() ==> r == self.eq_spec(other);
21
22 fn ne(&self, other: &Rhs) -> (r: bool)
23 ensures
24 Self::obeys_eq_spec() ==> r == !self.eq_spec(other),
25 default_ensures
26 call_ensures(Self::eq, (self, other), !r);
27}
28
29#[verifier::external_trait_specification]
30pub trait ExEq: PartialEq + PointeeSized {
31 type ExternalTraitSpecificationFor: Eq;
32}
33
34#[verifier::external_type_specification]
35#[verifier::external_body]
36#[verifier::accept_recursive_types(T)]
37pub struct ExAssertParamIsEq<T: Eq + PointeeSized>(core::cmp::AssertParamIsEq<T>);
38
39#[verifier::external_trait_specification]
40#[verifier::external_trait_extension(PartialOrdSpec via PartialOrdSpecImpl)]
41pub trait ExPartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
42 type ExternalTraitSpecificationFor: PartialOrd<Rhs>;
43
44 spec fn obeys_partial_cmp_spec() -> bool;
45
46 spec fn partial_cmp_spec(&self, other: &Rhs) -> Option<Ordering>;
47
48 fn partial_cmp(&self, other: &Rhs) -> (r: Option<Ordering>)
49 ensures
50 Self::obeys_partial_cmp_spec() ==> r == self.partial_cmp_spec(other);
51
52 fn lt(&self, other: &Rhs) -> (r: bool)
53 ensures
54 Self::obeys_partial_cmp_spec() ==>
55 (r <==> self.partial_cmp_spec(other) == Some(Ordering::Less)),
56 default_ensures
57 exists|o: Option<Ordering>|
58 {
59 &&& #[trigger] call_ensures(Self::partial_cmp, (self, other), o)
60 &&& r <==> o == Some(Ordering::Less)
61 }
62 ;
63
64 fn le(&self, other: &Rhs) -> (r: bool)
65 ensures
66 Self::obeys_partial_cmp_spec() ==>
67 (r <==> self.partial_cmp_spec(other) matches Some(
68 Ordering::Less
69 | Ordering::Equal,
70 )),
71 default_ensures
72 exists|o: Option<Ordering>|
73 {
74 &&& #[trigger] call_ensures(Self::partial_cmp, (self, other), o)
75 &&& r <==> o matches Some(
76 Ordering::Less
77 | Ordering::Equal,
78 )
79 }
80 ;
81
82 fn gt(&self, other: &Rhs) -> (r: bool)
83 ensures
84 Self::obeys_partial_cmp_spec() ==>
85 (r <==> self.partial_cmp_spec(other) == Some(Ordering::Greater)),
86 default_ensures
87 exists|o: Option<Ordering>|
88 {
89 &&& #[trigger] call_ensures(Self::partial_cmp, (self, other), o)
90 &&& r <==> o == Some(Ordering::Greater)
91 }
92 ;
93
94 fn ge(&self, other: &Rhs) -> (r: bool)
95 ensures
96 Self::obeys_partial_cmp_spec() ==>
97 (r <==> self.partial_cmp_spec(other) matches Some(
98 Ordering::Greater
99 | Ordering::Equal,
100 )),
101 default_ensures
102 exists|o: Option<Ordering>|
103 {
104 &&& #[trigger] call_ensures(Self::partial_cmp, (self, other), o)
105 &&& r <==> o matches Some(
106 Ordering::Greater
107 | Ordering::Equal,
108 )
109 }
110 ;
111}
112
113#[verifier::external_trait_specification]
114#[verifier::external_trait_extension(OrdSpec via OrdSpecImpl)]
115pub trait ExOrd: Eq + PartialOrd + PointeeSized {
116 type ExternalTraitSpecificationFor: Ord;
117
118 spec fn obeys_cmp_spec() -> bool;
119
120 spec fn cmp_spec(&self, other: &Self) -> Ordering;
121
122 fn cmp(&self, other: &Self) -> (r: Ordering)
123 ensures
124 Self::obeys_cmp_spec() ==> r == self.cmp_spec(other);
125
126 fn max(self, other: Self) -> (r: Self)
127 ensures
128 ({
129 &&& Self::obeys_cmp_spec()
130 &&& Self::obeys_partial_cmp_spec()
131 &&& other.partial_cmp_spec(&self) == Some(other.cmp_spec(&self))
132 }) ==> match other.cmp_spec(&self) {
133 Ordering::Less => r == self,
134 Ordering::Equal => r == other,
135 Ordering::Greater => r == other,
136 }
137 default_ensures
138 exists|b: bool|
139 {
140 &&& #[trigger] call_ensures(Self::lt, (&other, &self), b)
141 &&& b ==> r == self
142 &&& !b ==> r == other
143 }
144 ;
145
146 fn min(self, other: Self) -> (r: Self)
147 ensures
148 ({
149 &&& Self::obeys_cmp_spec()
150 &&& Self::obeys_partial_cmp_spec()
151 &&& other.partial_cmp_spec(&self) == Some(other.cmp_spec(&self))
152 }) ==> match other.cmp_spec(&self) {
153 Ordering::Less => r == other,
154 Ordering::Equal => r == self,
155 Ordering::Greater => r == self,
156 }
157 default_ensures
158 exists|b: bool|
159 {
160 &&& #[trigger] call_ensures(Self::lt, (&other, &self), b)
161 &&& b ==> r == other
162 &&& !b ==> r == self
163 }
164 ;
165
166 fn clamp(self, min: Self, max: Self) -> (r: Self)
167 requires
168 Self::obeys_partial_cmp_spec(),
170 min.partial_cmp_spec(&max) matches Some(
171 Ordering::Less
172 | Ordering::Equal,
173 ),
174 ensures
175 ({
176 &&& Self::obeys_cmp_spec()
177 &&& Self::obeys_partial_cmp_spec()
178 &&& self.partial_cmp_spec(&min) == Some(self.cmp_spec(&min))
179 &&& self.partial_cmp_spec(&max) == Some(self.cmp_spec(&max))
180 }) ==> match (self.cmp_spec(&min), self.cmp_spec(&max)) {
181 (Ordering::Less, _) => r == min,
182 (_, Ordering::Greater) => r == max,
183 _ => r == self,
184 }
185 default_ensures
186 exists|b1: bool|
187 {
188 &&& #[trigger] call_ensures(Self::lt, (&self, &min), b1)
189 &&& b1 ==> r == min
190 &&& !b1 ==> exists|b2: bool|
191 {
192 &&& #[trigger] call_ensures(Self::gt, (&self, &max), b2)
193 &&& b2 ==> r == max
194 &&& !b2 ==> r == self
195 }
196 }
197 ;
198}
199
200pub trait PartialEqIs<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
201 spec fn is_eq(&self, other: &Rhs) -> bool;
202
203 spec fn is_ne(&self, other: &Rhs) -> bool;
204}
205
206pub trait PartialOrdIs<Rhs: PointeeSized = Self>: PartialOrd<Rhs> + PointeeSized {
207 spec fn is_lt(&self, other: &Rhs) -> bool;
208
209 spec fn is_le(&self, other: &Rhs) -> bool;
210
211 spec fn is_gt(&self, other: &Rhs) -> bool;
212
213 spec fn is_ge(&self, other: &Rhs) -> bool;
214}
215
216impl<A: PointeeSized + PartialEq<Rhs>, Rhs: PointeeSized> PartialEqIs<Rhs> for A {
217 #[verifier::inline]
218 open spec fn is_eq(&self, other: &Rhs) -> bool {
219 self.eq_spec(other)
220 }
221
222 #[verifier::inline]
223 open spec fn is_ne(&self, other: &Rhs) -> bool {
224 !self.eq_spec(other)
225 }
226}
227
228impl<A: PointeeSized + PartialOrd<Rhs>, Rhs: PointeeSized> PartialOrdIs<Rhs> for A {
229 #[verifier::inline]
230 open spec fn is_lt(&self, other: &Rhs) -> bool {
231 self.partial_cmp_spec(other) == Some(Ordering::Less)
232 }
233
234 #[verifier::inline]
235 open spec fn is_le(&self, other: &Rhs) -> bool {
236 matches!(self.partial_cmp_spec(other), Some(Ordering::Less | Ordering::Equal))
237 }
238
239 #[verifier::inline]
240 open spec fn is_gt(&self, other: &Rhs) -> bool {
241 self.partial_cmp_spec(other) == Some(Ordering::Greater)
242 }
243
244 #[verifier::inline]
245 open spec fn is_ge(&self, other: &Rhs) -> bool {
246 matches!(self.partial_cmp_spec(other), Some(Ordering::Greater | Ordering::Equal))
247 }
248}
249
250impl PartialEqSpecImpl for bool {
253 open spec fn obeys_eq_spec() -> bool {
254 true
255 }
256
257 open spec fn eq_spec(&self, other: &bool) -> bool {
258 *self == *other
259 }
260}
261
262pub assume_specification[ <bool as PartialEq<bool>>::eq ](x: &bool, y: &bool) -> bool;
263
264pub assume_specification[ <bool as PartialEq<bool>>::ne ](x: &bool, y: &bool) -> bool;
265
266pub uninterp spec fn eq_ensures<A>(x: A, y: A, o: bool) -> bool;
277
278pub uninterp spec fn ne_ensures<A>(x: A, y: A, o: bool) -> bool;
279
280pub uninterp spec fn partial_cmp_ensures<A>(x: A, y: A, o: Option<Ordering>) -> bool;
281
282pub uninterp spec fn lt_ensures<A>(x: A, y: A, o: bool) -> bool;
283
284pub uninterp spec fn le_ensures<A>(x: A, y: A, o: bool) -> bool;
285
286pub uninterp spec fn gt_ensures<A>(x: A, y: A, o: bool) -> bool;
287
288pub uninterp spec fn ge_ensures<A>(x: A, y: A, o: bool) -> bool;
289
290pub assume_specification[ <f32 as PartialEq<f32>>::eq ](x: &f32, y: &f32) -> (o: bool)
292 ensures
293 eq_ensures::<f32>(*x, *y, o),
294;
295
296pub assume_specification[ <f32 as PartialEq<f32>>::ne ](x: &f32, y: &f32) -> (o: bool)
298 ensures
299 ne_ensures::<f32>(*x, *y, o),
300;
301
302pub assume_specification[ <f32 as PartialOrd<f32>>::partial_cmp ](x: &f32, y: &f32) -> (o: Option<Ordering>)
303 ensures
304 partial_cmp_ensures::<f32>(*x, *y, o),
305;
306
307pub assume_specification[ <f32 as PartialOrd<f32>>::lt ](x: &f32, y: &f32) -> (o: bool)
308 ensures
309 lt_ensures::<f32>(*x, *y, o),
310;
311
312pub assume_specification[ <f32 as PartialOrd<f32>>::le ](x: &f32, y: &f32) -> (o: bool)
313 ensures
314 le_ensures::<f32>(*x, *y, o),
315;
316
317pub assume_specification[ <f32 as PartialOrd<f32>>::gt ](x: &f32, y: &f32) -> (o: bool)
318 ensures
319 gt_ensures::<f32>(*x, *y, o),
320;
321
322pub assume_specification[ <f32 as PartialOrd<f32>>::ge ](x: &f32, y: &f32) -> (o: bool)
323 ensures
324 ge_ensures::<f32>(*x, *y, o),
325;
326
327pub assume_specification[ <f64 as PartialEq<f64>>::eq ](x: &f64, y: &f64) -> (o: bool)
329 ensures
330 eq_ensures::<f64>(*x, *y, o),
331;
332
333pub assume_specification[ <f64 as PartialEq<f64>>::ne ](x: &f64, y: &f64) -> (o: bool)
335 ensures
336 ne_ensures::<f64>(*x, *y, o),
337;
338
339pub assume_specification[ <f64 as PartialOrd<f64>>::partial_cmp ](x: &f64, y: &f64) -> (o: Option<Ordering>)
340 ensures
341 partial_cmp_ensures::<f64>(*x, *y, o),
342;
343
344pub assume_specification[ <f64 as PartialOrd<f64>>::lt ](x: &f64, y: &f64) -> (o: bool)
345 ensures
346 lt_ensures::<f64>(*x, *y, o),
347;
348
349pub assume_specification[ <f64 as PartialOrd<f64>>::le ](x: &f64, y: &f64) -> (o: bool)
350 ensures
351 le_ensures::<f64>(*x, *y, o),
352;
353
354pub assume_specification[ <f64 as PartialOrd<f64>>::gt ](x: &f64, y: &f64) -> (o: bool)
355 ensures
356 gt_ensures::<f64>(*x, *y, o),
357;
358
359pub assume_specification[ <f64 as PartialOrd<f64>>::ge ](x: &f64, y: &f64) -> (o: bool)
360 ensures
361 ge_ensures::<f64>(*x, *y, o),
362;
363
364impl<A: PointeeSized, B: PointeeSized> PartialEqSpecImpl<&B> for &A
367where
368 A: PartialEq<B>,
369{
370 open spec fn obeys_eq_spec() -> bool {
371 <A as PartialEqSpec<B>>::obeys_eq_spec()
372 }
373
374 open spec fn eq_spec(&self, other: &&B) -> bool {
375 <A as PartialEqSpec<B>>::eq_spec(*self, *other)
376 }
377}
378
379pub assume_specification<'_0, 'a, A: PointeeSized, B: PointeeSized>[ <&'a A as PartialEq<&B>>::eq ](
380 a: &&'a A,
381 b: &&B,
382) -> bool
383where
384 A: PartialEq<B>,
385;
386
387pub assume_specification<'_0, 'a, A: PointeeSized, B: PointeeSized>[ <&'a A as PartialEq<&B>>::ne ](
388 a: &&'a A,
389 b: &&B,
390) -> bool
391where
392 A: PartialEq<B>,
393;
394
395impl<A: PointeeSized, B: PointeeSized> PartialOrdSpecImpl<&B> for &A
396where
397 A: PartialOrd<B>,
398{
399 open spec fn obeys_partial_cmp_spec() -> bool {
400 <A as PartialOrdSpec<B>>::obeys_partial_cmp_spec()
401 }
402
403 open spec fn partial_cmp_spec(&self, other: &&B) -> Option<core::cmp::Ordering> {
404 <A as PartialOrdSpec<B>>::partial_cmp_spec(*self, *other)
405 }
406}
407
408pub assume_specification<'_0, 'a, A: PointeeSized, B: PointeeSized>[ <&'a A as PartialOrd<&B>>::partial_cmp ](
409 a: &&'a A,
410 b: &&B,
411) -> Option<core::cmp::Ordering>
412where
413 A: PartialOrd<B>,
414;
415
416pub assume_specification<'_0, 'a, A: PointeeSized, B: PointeeSized>[ <&'a A as PartialOrd<&B>>::lt ](
417 a: &&'a A,
418 b: &&B,
419) -> bool
420where
421 A: PartialOrd<B>,
422;
423
424pub assume_specification<'_0, 'a, A: PointeeSized, B: PointeeSized>[ <&'a A as PartialOrd<&B>>::le ](
425 a: &&'a A,
426 b: &&B,
427) -> bool
428where
429 A: PartialOrd<B>,
430;
431
432pub assume_specification<'_0, 'a, A: PointeeSized, B: PointeeSized>[ <&'a A as PartialOrd<&B>>::gt ](
433 a: &&'a A,
434 b: &&B,
435) -> bool
436where
437 A: PartialOrd<B>,
438;
439
440pub assume_specification<'_0, 'a, A: PointeeSized, B: PointeeSized>[ <&'a A as PartialOrd<&B>>::ge ](
441 a: &&'a A,
442 b: &&B,
443) -> bool
444where
445 A: PartialOrd<B>,
446;
447
448impl<A: PointeeSized + Ord> OrdSpecImpl for &A {
449 open spec fn obeys_cmp_spec() -> bool {
450 A::obeys_cmp_spec()
451 }
452
453 open spec fn cmp_spec(&self, other: &Self) -> core::cmp::Ordering {
454 A::cmp_spec(*self, *other)
455 }
456}
457
458pub assume_specification<'a, A: PointeeSized + Ord>[ <&'a A as Ord>::cmp ](
459 a: &&'a A,
460 b: &&'a A,
461) -> core::cmp::Ordering
462;
463
464} macro_rules! tuple_cmp_impl {
467 ($($idx:tt $T:ident, )+) => {
468 verus! {
469 impl<$($T: PartialEq + PartialEqSpec),+> PartialEqSpecImpl for ($($T,)+)
470 {
471 open spec fn obeys_eq_spec() -> bool {
472 $(&&& $T::obeys_eq_spec())+
473 }
474
475 open spec fn eq_spec(&self, other: &($($T,)+)) -> bool {
476 $(&&& $T::eq_spec(&self.$idx, &other.$idx ))+
477 }
478 }
479
480 impl<$($T: PartialOrd + PartialOrdSpec),+> PartialOrdSpecImpl for ($($T,)+)
481 {
482 open spec fn obeys_partial_cmp_spec() -> bool {
483 $(&&& $T::obeys_partial_cmp_spec())+
484 }
485
486 open spec fn partial_cmp_spec(&self, other: &($($T,)+)) -> Option<core::cmp::Ordering> {
487 lexical_partial_cmp_spec!($( self.$idx, other.$idx ),+)
488 }
489 }
490
491 impl<$($T: Ord + OrdSpec),+> OrdSpecImpl for ($($T,)+)
492 {
493 open spec fn obeys_cmp_spec() -> bool {
494 $(&&& $T::obeys_cmp_spec())+
495 }
496
497 open spec fn cmp_spec(&self, other: &($($T,)+)) -> core::cmp::Ordering {
498 lexical_cmp_spec!($( self.$idx, other.$idx ),+)
499 }
500 }
501
502 }
503 };
504}
505
506#[allow(unused)]
507macro_rules! lexical_partial_cmp_spec {
508 ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
509 match ($a).partial_cmp_spec(&$b) {
510 Some(core::cmp::Ordering::Equal) => lexical_partial_cmp_spec!($($rest_a, $rest_b),+),
511 ordering => ordering
512 }
513 };
514 ($a:expr, $b:expr) => { ($a).partial_cmp_spec(&$b) };
515}
516
517#[allow(unused)]
518macro_rules! lexical_cmp_spec {
519 ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
520 match ($a).cmp_spec(&$b) {
521 core::cmp::Ordering::Equal => lexical_cmp_spec!($($rest_a, $rest_b),+),
522 ordering => ordering
523 }
524 };
525 ($a:expr, $b:expr) => { ($a).cmp_spec(&$b) };
526}
527
528tuple_cmp_impl!(0 T, );
529tuple_cmp_impl!(0 U, 1 T, );
530tuple_cmp_impl!(0 V, 1 U, 2 T, );
531tuple_cmp_impl!(0 W, 1 V, 2 U, 3 T, );
532tuple_cmp_impl!(0 X, 1 W, 2 V, 3 U, 4 T, );
533tuple_cmp_impl!(0 Y, 1 X, 2 W, 3 V, 4 U, 5 T, );
534tuple_cmp_impl!(0 Z, 1 Y, 2 X, 3 W, 4 V, 5 U, 6 T, );
535tuple_cmp_impl!(0 A, 1 Z, 2 Y, 3 X, 4 W, 5 V, 6 U, 7 T, );
536tuple_cmp_impl!(0 B, 1 A, 2 Z, 3 Y, 4 X, 5 W, 6 V, 7 U, 8 T, );
537tuple_cmp_impl!(0 C, 1 B, 2 A, 3 Z, 4 Y, 5 X, 6 W, 7 V, 8 U, 9 T, );
538tuple_cmp_impl!(0 D, 1 C, 2 B, 3 A, 4 Z, 5 Y, 6 X, 7 W, 8 V, 9 U, 10 T, );
539tuple_cmp_impl!(0 E, 1 D, 2 C, 3 B, 4 A, 5 Z, 6 Y, 7 X, 8 W, 9 V, 10 U, 11 T, );