1use crate::{prelude::*, std::iter::ExactSizeIteratorSpec};
2#[cfg(feature = "nightly")]
3use core::iter::Step;
4use core::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
37extern_spec! {
38 impl<Idx: DeepModel<DeepModelTy = Int> + Step> Iterator for Range<Idx> {
39 #[ensures(self.start.deep_model() >= self.end.deep_model() ==>
40 result == (0usize, Some(0usize)))]
41 #[ensures({
42 let s = self.end.deep_model() - self.start.deep_model();
43 s >= 0 && s <= usize::MAX@ ==>
44 result.0@ == s && result.1 == Some(result.0)
45 })]
46 #[ensures(self.end.deep_model() - self.start.deep_model() > usize::MAX@ ==>
47 result == (usize::MAX, None))]
48 fn size_hint(&self) -> (usize, Option<usize>);
49 }
50}
51
52macro_rules! impl_exact_size_range {
53 ($($t:ty)*) => ($(
54 impl ExactSizeIteratorSpec for Range<$t> {
55 #[logic(law)]
56 #[requires(Self::size_hint.postcondition((self,), r))]
57 #[ensures(r.1 == Some(r.0))]
58 #[allow(unused_variables)]
59 fn size_hint_exact(&self, r: (usize, Option<usize>)) {}
60 }
61 )*)
62}
63
64impl_exact_size_range! { i8 u8 i16 u16 isize usize }
65
66#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
69impl_exact_size_range! { i32 u32 }
70
71#[cfg(feature = "nightly")]
72impl<Idx: DeepModel<DeepModelTy = Int> + Step> DoubleEndedIteratorSpec for Range<Idx> {
73 #[logic(open)]
74 fn produces_back(self, visited: Seq<Self::Item>, o: Self) -> bool {
75 pearlite! {
76 self.start == o.start && self.end.deep_model() >= o.end.deep_model()
77 && (visited.len() > 0 ==> o.end.deep_model() >= o.start.deep_model())
78 && visited.len() == self.end.deep_model() - o.end.deep_model()
79 && forall<i> 0 <= i && i < visited.len() ==>
80 visited[i].deep_model() == self.end.deep_model() - i - 1
81 }
82 }
83
84 #[logic(open, prophetic)]
85 fn completed_back(&mut self) -> bool {
86 self.completed()
87 }
88
89 #[logic(law)]
90 #[ensures(self.produces_back(Seq::empty(), self))]
91 fn produces_back_refl(self) {}
92
93 #[logic(law)]
94 #[requires(a.produces_back(ab, b))]
95 #[requires(b.produces_back(bc, c))]
96 #[ensures(a.produces_back(ab.concat(bc), c))]
97 fn produces_back_trans(a: Self, ab: Seq<Self::Item>, b: Self, bc: Seq<Self::Item>, c: Self) {}
98
99 #[logic(law)]
100 #[requires(Self::size_hint.postcondition((self,), r))]
101 #[ensures(forall<s: Seq<Self::Item>, i: &mut Self>
102 self.produces_back(s, *i) && i.completed_back() ==> r.0@ <= s.len())]
103 #[ensures(match r.1 {
104 Some(r) => {
105 forall<s: Seq<Self::Item>, i: Self> self.produces_back(s, i) ==> s.len() <= r@
106 }
107 None => true
108 })]
109 fn size_hint_back_spec(&self, r: (usize, Option<usize>)) {}
110}
111
112#[logic(open)]
113#[ensures(r.is_empty_log() == (result == 0))]
114pub fn range_inclusive_len<Idx: DeepModel<DeepModelTy = Int>>(r: RangeInclusive<Idx>) -> Int {
115 if r.is_empty_log() { 0 } else { r.end_log().deep_model() - r.start_log().deep_model() + 1 }
116}
117
118#[cfg(feature = "nightly")]
119impl<Idx: DeepModel<DeepModelTy = Int> + Step> IteratorSpec for RangeInclusive<Idx> {
120 #[logic(open, prophetic)]
121 fn completed(&mut self) -> bool {
122 pearlite! {
123 self.is_empty_log() && (^self).is_empty_log()
124 }
125 }
126
127 #[logic(open)]
128 fn produces(self, visited: Seq<Self::Item>, o: Self) -> bool {
129 pearlite! {
130 visited.len() == range_inclusive_len(self) - range_inclusive_len(o) &&
131 (self.is_empty_log() ==> o.is_empty_log()) &&
132 (o.is_empty_log() || self.end_log() == o.end_log()) &&
133 forall<i> 0 <= i && i < visited.len() ==>
134 visited[i].deep_model() == self.start_log().deep_model() + i
135 }
136 }
137
138 #[logic(law)]
139 #[ensures(self.produces(Seq::empty(), self))]
140 fn produces_refl(self) {}
141
142 #[logic(law)]
143 #[requires(a.produces(ab, b))]
144 #[requires(b.produces(bc, c))]
145 #[ensures(a.produces(ab.concat(bc), c))]
146 fn produces_trans(a: Self, ab: Seq<Self::Item>, b: Self, bc: Seq<Self::Item>, c: Self) {}
147}
148
149extern_spec! {
150 impl<Idx: DeepModel<DeepModelTy = Int> + Step> Iterator for RangeInclusive<Idx> {
151 #[ensures({
152 let s = range_inclusive_len(*self);
153 s <= usize::MAX@ ==> result.0@ == s && result.1 == Some(result.0)
154 })]
155 #[ensures(range_inclusive_len(*self) > usize::MAX@ ==>
156 result == (usize::MAX, None))]
157 fn size_hint(&self) -> (usize, Option<usize>);
158 }
159}
160
161macro_rules! impl_exact_size_range_inclusive {
162 ($($t:ty)*) => ($(
163 impl ExactSizeIteratorSpec for RangeInclusive<$t> {
164 #[logic(law)]
165 #[requires(Self::size_hint.postcondition((self,), r))]
166 #[ensures(r.1 == Some(r.0))]
167 #[allow(unused_variables)]
168 fn size_hint_exact(&self, r: (usize, Option<usize>)) {}
169 }
170 )*)
171}
172
173impl_exact_size_range_inclusive! { i8 u8 }
174
175#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
176impl_exact_size_range_inclusive! { i16 u16 }
177
178#[cfg(feature = "nightly")]
179impl<Idx: DeepModel<DeepModelTy = Int> + Step> DoubleEndedIteratorSpec for RangeInclusive<Idx> {
180 #[logic(open)]
181 fn produces_back(self, visited: Seq<Self::Item>, o: Self) -> bool {
182 pearlite! {
183 visited.len() == range_inclusive_len(self) - range_inclusive_len(o) &&
184 (self.is_empty_log() ==> o.is_empty_log()) &&
185 (o.is_empty_log() || self.start_log() == o.start_log()) &&
186 forall<i> 0 <= i && i < visited.len() ==>
187 visited[i].deep_model() == self.end_log().deep_model() - i
188 }
189 }
190
191 #[logic(open, prophetic)]
192 fn completed_back(&mut self) -> bool {
193 self.completed()
194 }
195
196 #[logic(law)]
197 #[ensures(self.produces_back(Seq::empty(), self))]
198 fn produces_back_refl(self) {}
199
200 #[logic(law)]
201 #[requires(a.produces_back(ab, b))]
202 #[requires(b.produces_back(bc, c))]
203 #[ensures(a.produces_back(ab.concat(bc), c))]
204 fn produces_back_trans(a: Self, ab: Seq<Self::Item>, b: Self, bc: Seq<Self::Item>, c: Self) {}
205
206 #[logic(law)]
207 #[requires(Self::size_hint.postcondition((self,), r))]
208 #[ensures(forall<s: Seq<Self::Item>, i: &mut Self>
209 self.produces_back(s, *i) && i.completed_back() ==> r.0@ <= s.len())]
210 #[ensures(match r.1 {
211 Some(r) => {
212 forall<s: Seq<Self::Item>, i: Self> self.produces_back(s, i) ==> s.len() <= r@
213 }
214 None => true
215 })]
216 fn size_hint_back_spec(&self, r: (usize, Option<usize>)) {}
217}
218
219#[cfg(not(feature = "nightly"))]
221macro_rules! impl_range {
222 ( $( $ty:tt ),+ ) => {
223 $(
224 impl IteratorSpec for Range<$ty> {}
225 impl IteratorSpec for RangeInclusive<$ty> {}
226 impl DoubleEndedIteratorSpec for Range<$ty> {}
227 impl DoubleEndedIteratorSpec for RangeInclusive<$ty> {}
228 )+
229 };
230}
231
232#[cfg(not(feature = "nightly"))]
233impl_range! { char, i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize }