1use crate::{partial_ord_laws_impl, prelude::*};
2use core::cmp::*;
3
4#[cfg(creusot)]
5pub use creusot_std_proc::PartialEq;
6
7#[cfg(not(creusot))]
8pub use core::cmp::PartialEq;
9
10extern_spec! {
11 mod core {
12 mod cmp {
13 trait PartialEq<Rhs: ?Sized + DeepModel<DeepModelTy = Self::DeepModelTy>>: DeepModel {
14 #[ensures(result == (self.deep_model() == rhs.deep_model()))]
15 fn eq(&self, rhs: &Rhs) -> bool;
16
17 #[ensures(result == (self.deep_model() != rhs.deep_model()))]
18 fn ne(&self, rhs: &Rhs) -> bool {
19 !(self == rhs)
20 }
21 }
22
23 trait PartialOrd<Rhs: ?Sized + DeepModel<DeepModelTy = Self::DeepModelTy>>:
24 DeepModel<DeepModelTy: PartialOrdLogic>
25 {
26 #[ensures(result == (*self).deep_model().partial_cmp_log((*rhs).deep_model()))]
27 fn partial_cmp(&self, rhs: &Rhs) -> Option<Ordering>;
28
29 #[ensures(result == (self.deep_model() < other.deep_model()))]
30 fn lt(&self, other: &Rhs) -> bool {
31 match self.partial_cmp(other) {
32 Some(Ordering::Less) => true,
33 _ => false,
34 }
35 }
36
37 #[ensures(result == (self.deep_model() <= other.deep_model()))]
38 fn le(&self, other: &Rhs) -> bool {
39 match self.partial_cmp(other) {
40 Some(Ordering::Less | Ordering::Equal) => true,
41 _ => false,
42 }
43 }
44
45 #[ensures(result == (self.deep_model() > other.deep_model()))]
46 fn gt(&self, other: &Rhs) -> bool {
47 match self.partial_cmp(other) {
48 Some(Ordering::Greater) => true,
49 _ => false,
50 }
51 }
52
53 #[ensures(result == (self.deep_model() >= other.deep_model()))]
54 fn ge(&self, other: &Rhs) -> bool {
55 match self.partial_cmp(other) {
56 Some(Ordering::Greater | Ordering::Equal) => true,
57 _ => false,
58 }
59 }
60 }
61
62 trait Ord: DeepModel<DeepModelTy: OrdLogic> {
63 #[ensures(result == (*self).deep_model().cmp_log((*rhs).deep_model()))]
64 fn cmp(&self, rhs: &Self) -> Ordering;
65
66 #[ensures(result.deep_model() >= self.deep_model())]
67 #[ensures(result.deep_model() >= o.deep_model())]
68 #[ensures(result == self || result == o)]
69 #[ensures(self.deep_model() <= o.deep_model() ==> result == o)]
70 #[ensures(o.deep_model() < self.deep_model() ==> result == self)]
71 fn max(self, o: Self) -> Self where Self: Sized {
72 let _ = snapshot!(Self::DeepModelTy::lt_log_total);
73 if self <= o { o } else { self }
74 }
75
76 #[ensures(result.deep_model() <= self.deep_model())]
77 #[ensures(result.deep_model() <= o.deep_model())]
78 #[ensures(result == self || result == o)]
79 #[ensures(self.deep_model() < o.deep_model() ==> result == self)]
80 #[ensures(o.deep_model() <= self.deep_model() ==> result == o)]
81 fn min(self, o: Self) -> Self where Self: Sized {
82 let _ = snapshot!(Self::DeepModelTy::lt_log_total);
83 if self < o { self } else { o }
84 }
85
86 #[requires(min.deep_model() <= max.deep_model())]
87 #[ensures(result.deep_model() >= min.deep_model())]
88 #[ensures(result.deep_model() <= max.deep_model())]
89 #[ensures(result == self || result == min || result == max)]
90 #[ensures(if self.deep_model() > max.deep_model() {
91 result == max
92 } else if self.deep_model() < min.deep_model() {
93 result == min
94 } else { result == self })]
95 fn clamp(self, min: Self, max: Self) -> Self where Self: Sized {
96 let _ = snapshot!(Self::DeepModelTy::lt_log_total);
97 if self > max { max } else if self < min { min } else { self }
98 }
99 }
100
101 #[ensures(result.deep_model() >= v1.deep_model())]
102 #[ensures(result.deep_model() >= v2.deep_model())]
103 #[ensures(result == v1 || result == v2)]
104 #[ensures(v1.deep_model() <= v2.deep_model() ==> result == v2)]
105 #[ensures(v2.deep_model() < v1.deep_model() ==> result == v1)]
106 fn max<T: Ord + DeepModel<DeepModelTy: OrdLogic>>(v1: T, v2: T) -> T {
107 <T as Ord>::max(v1, v2)
108 }
109
110 #[ensures(result.deep_model() <= v1.deep_model())]
111 #[ensures(result.deep_model() <= v2.deep_model())]
112 #[ensures(result == v1 || result == v2)]
113 #[ensures(v1.deep_model() < v2.deep_model() ==> result == v1)]
114 #[ensures(v2.deep_model() <= v1.deep_model() ==> result == v2)]
115 fn min<T: Ord + DeepModel<DeepModelTy: OrdLogic>>(v1: T, v2: T) -> T {
116 <T as Ord>::min(v1, v2)
117 }
118 }
119 }
120}
121
122macro_rules! impl_cmp_int {
124 ($($t:ty)*) => {
125$(
126
127extern_spec! {
128 impl PartialEq<$t> for $t {
129 #[check(ghost)]
130 #[ensures(result == (self.deep_model() == rhs.deep_model()))]
131 fn eq(&self, rhs: &$t) -> bool;
132
133 #[check(ghost)]
134 #[ensures(result == (self.deep_model() != rhs.deep_model()))]
135 fn ne(&self, rhs: &$t) -> bool;
136 }
137
138 impl PartialOrd<$t> for $t
139 {
140 #[check(ghost)]
141 #[ensures(result == (*self).deep_model().partial_cmp_log((*rhs).deep_model()))]
142 fn partial_cmp(&self, rhs: &$t) -> Option<Ordering>;
143
144 #[check(ghost)]
145 #[ensures(result == (self.deep_model() < other.deep_model()))]
146 fn lt(&self, other: &$t) -> bool {
147 match self.partial_cmp(other) {
148 Some(Ordering::Less) => true,
149 _ => false,
150 }
151 }
152
153 #[check(ghost)]
154 #[ensures(result == (self.deep_model() <= other.deep_model()))]
155 fn le(&self, other: &$t) -> bool {
156 match self.partial_cmp(other) {
157 Some(Ordering::Less | Ordering::Equal) => true,
158 _ => false,
159 }
160 }
161
162 #[check(ghost)]
163 #[ensures(result == (self.deep_model() > other.deep_model()))]
164 fn gt(&self, other: &$t) -> bool {
165 match self.partial_cmp(other) {
166 Some(Ordering::Greater) => true,
167 _ => false,
168 }
169 }
170
171 #[check(ghost)]
172 #[ensures(result == (self.deep_model() >= other.deep_model()))]
173 fn ge(&self, other: &$t) -> bool {
174 match self.partial_cmp(other) {
175 Some(Ordering::Greater | Ordering::Equal) => true,
176 _ => false,
177 }
178 }
179 }
180
181 impl Ord for $t
182 {
183 #[check(ghost)]
184 #[ensures(result == (*self).deep_model().cmp_log((*rhs).deep_model()))]
185 fn cmp(&self, rhs: &Self) -> Ordering;
186
187 }
220}
221
222)* };
223
224}
225
226impl_cmp_int!(i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize);
227
228impl<T: DeepModel> DeepModel for Reverse<T> {
229 type DeepModelTy = Reverse<T::DeepModelTy>;
230
231 #[logic(open, inline)]
232 fn deep_model(self) -> Self::DeepModelTy {
233 pearlite! { Reverse(self.0.deep_model()) }
234 }
235}
236
237impl<T: PartialOrdLogic> PartialOrdLogic for Reverse<T> {
238 #[logic(open, inline)]
239 fn lt_log(self, o: Self) -> bool {
240 o.0 < self.0
241 }
242
243 #[logic(open, inline)]
244 fn le_log(self, o: Self) -> bool {
245 o.0 <= self.0
246 }
247
248 partial_ord_laws_impl! {}
249}