creusot_contracts/std/iter/
range.rs1use crate::prelude::*;
2#[cfg(feature = "nightly")]
3use std::iter::Step;
4use std::ops::{Range, RangeInclusive};
5
6#[cfg(feature = "nightly")]
7impl<Idx: DeepModel<DeepModelTy = Int> + Step> IteratorSpec for Range<Idx> {
8 #[logic(open, prophetic)]
9 fn completed(&mut self) -> bool {
10 pearlite! {
11 resolve(self) && self.start.deep_model() >= self.end.deep_model()
12 }
13 }
14
15 #[logic(open)]
16 fn produces(self, visited: Seq<Self::Item>, o: Self) -> bool {
17 pearlite! {
18 self.end == o.end && self.start.deep_model() <= o.start.deep_model()
19 && (visited.len() > 0 ==> o.start.deep_model() <= o.end.deep_model())
20 && visited.len() == o.start.deep_model() - self.start.deep_model()
21 && forall<i> 0 <= i && i < visited.len() ==>
22 visited[i].deep_model() == self.start.deep_model() + i
23 }
24 }
25
26 #[logic(law)]
27 #[ensures(self.produces(Seq::empty(), self))]
28 fn produces_refl(self) {}
29
30 #[logic(law)]
31 #[requires(a.produces(ab, b))]
32 #[requires(b.produces(bc, c))]
33 #[ensures(a.produces(ab.concat(bc), c))]
34 fn produces_trans(a: Self, ab: Seq<Self::Item>, b: Self, bc: Seq<Self::Item>, c: Self) {}
35}
36
37#[cfg(feature = "nightly")]
38impl<Idx: DeepModel<DeepModelTy = Int> + Step> DoubleEndedIteratorSpec for Range<Idx> {
39 #[logic(open)]
40 fn produces_back(self, visited: Seq<Self::Item>, o: Self) -> bool {
41 pearlite! {
42 self.start == o.start && self.end.deep_model() >= o.end.deep_model()
43 && (visited.len() > 0 ==> o.end.deep_model() >= o.start.deep_model())
44 && visited.len() == o.end.deep_model() - self.end.deep_model()
45 && forall<i> 0 <= i && i < visited.len() ==>
46 visited[i].deep_model() == self.end.deep_model() - i
47 }
48 }
49
50 #[logic(law)]
51 #[ensures(self.produces_back(Seq::empty(), self))]
52 fn produces_back_refl(self) {}
53
54 #[logic(law)]
55 #[requires(a.produces_back(ab, b))]
56 #[requires(b.produces_back(bc, c))]
57 #[ensures(a.produces_back(ab.concat(bc), c))]
58 fn produces_back_trans(a: Self, ab: Seq<Self::Item>, b: Self, bc: Seq<Self::Item>, c: Self) {}
59}
60
61#[logic(open)]
62#[ensures(r.is_empty_log() == (result == 0))]
63pub fn range_inclusive_len<Idx: DeepModel<DeepModelTy = Int>>(r: RangeInclusive<Idx>) -> Int {
64 pearlite! {
65 if r.is_empty_log() { 0 }
66 else { r.end_log().deep_model() - r.start_log().deep_model() + 1 }
67 }
68}
69
70#[cfg(feature = "nightly")]
71impl<Idx: DeepModel<DeepModelTy = Int> + Step> IteratorSpec for RangeInclusive<Idx> {
72 #[logic(open, prophetic)]
73 fn completed(&mut self) -> bool {
74 pearlite! {
75 self.is_empty_log() && (^self).is_empty_log()
76 }
77 }
78
79 #[logic(open)]
80 fn produces(self, visited: Seq<Self::Item>, o: Self) -> bool {
81 pearlite! {
82 visited.len() == range_inclusive_len(self) - range_inclusive_len(o) &&
83 (self.is_empty_log() ==> o.is_empty_log()) &&
84 (o.is_empty_log() || self.end_log() == o.end_log()) &&
85 forall<i> 0 <= i && i < visited.len() ==>
86 visited[i].deep_model() == self.start_log().deep_model() + i
87 }
88 }
89
90 #[logic(open, law)]
91 #[ensures(self.produces(Seq::empty(), self))]
92 fn produces_refl(self) {}
93
94 #[logic(open, law)]
95 #[requires(a.produces(ab, b))]
96 #[requires(b.produces(bc, c))]
97 #[ensures(a.produces(ab.concat(bc), c))]
98 fn produces_trans(a: Self, ab: Seq<Self::Item>, b: Self, bc: Seq<Self::Item>, c: Self) {}
99}
100
101#[cfg(feature = "nightly")]
102impl<Idx: DeepModel<DeepModelTy = Int> + Step> DoubleEndedIteratorSpec for RangeInclusive<Idx> {
103 #[logic(open)]
104 fn produces_back(self, visited: Seq<Self::Item>, o: Self) -> bool {
105 pearlite! {
106 visited.len() == range_inclusive_len(self) - range_inclusive_len(o) &&
107 (self.is_empty_log() ==> o.is_empty_log()) &&
108 (o.is_empty_log() || self.start_log() == o.start_log()) &&
109 forall<i> 0 <= i && i < visited.len() ==>
110 visited[i].deep_model() == self.end_log().deep_model() - i
111 }
112 }
113
114 #[logic(open, law)]
115 #[ensures(self.produces_back(Seq::empty(), self))]
116 fn produces_back_refl(self) {}
117
118 #[logic(open, law)]
119 #[requires(a.produces_back(ab, b))]
120 #[requires(b.produces_back(bc, c))]
121 #[ensures(a.produces_back(ab.concat(bc), c))]
122 fn produces_back_trans(a: Self, ab: Seq<Self::Item>, b: Self, bc: Seq<Self::Item>, c: Self) {}
123}
124
125#[cfg(not(feature = "nightly"))]
127macro_rules! impl_range {
128 ( $( $ty:tt ),+ ) => {
129 $(
130 impl IteratorSpec for Range<$ty> {}
131 impl IteratorSpec for RangeInclusive<$ty> {}
132 impl DoubleEndedIteratorSpec for Range<$ty> {}
133 impl DoubleEndedIteratorSpec for RangeInclusive<$ty> {}
134 )+
135 };
136}
137
138#[cfg(not(feature = "nightly"))]
139impl_range! { char, i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize }