Skip to main content

creusot_std/std/
cmp.rs

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
122// Make equality and comparisons on integers pure operations.
123macro_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        // TODO: cannot write a `#[check(ghost)]` extern specs for the rest of the
188        // items, because they have a default implementation, which means we
189        // cannot differentiate an extern spec for `Ord::max` from a one for
190        // `<$t as Ord>::max`.
191
192        // #[check(ghost)]
193        // #[ensures(result.deep_model() >= self.deep_model())]
194        // #[ensures(result.deep_model() >= o.deep_model())]
195        // #[ensures(result == self || result == o)]
196        // #[ensures(self.deep_model() <= o.deep_model() ==> result == o)]
197        // #[ensures(o.deep_model() < self.deep_model() ==> result == self)]
198        // fn max(self, o: Self) -> Self;
199
200        // #[check(ghost)]
201        // #[ensures(result.deep_model() <= self.deep_model())]
202        // #[ensures(result.deep_model() <= o.deep_model())]
203        // #[ensures(result == self || result == o)]
204        // #[ensures(self.deep_model() < o.deep_model() ==> result == self)]
205        // #[ensures(o.deep_model() <= self.deep_model() ==> result == o)]
206        // fn min(self, o: Self) -> Self;
207
208        // #[check(ghost)]
209        // #[requires(min.deep_model() <= max.deep_model())]
210        // #[ensures(result.deep_model() >= min.deep_model())]
211        // #[ensures(result.deep_model() <= max.deep_model())]
212        // #[ensures(result == self || result == min || result == max)]
213        // #[ensures(if self.deep_model() > max.deep_model() {
214        //     result == max
215        // } else if self.deep_model() < min.deep_model() {
216        //     result == min
217        // } else { result == self })]
218        // fn clamp(self, min: Self, max: Self) -> Self;
219    }
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}