1use crate::{
2 logic::FMap,
3 prelude::*,
4 std::iter::{ExactSizeIteratorSpec, IteratorSpec},
5};
6#[cfg(feature = "nightly")]
7use std::alloc::Allocator;
8use std::collections::hash_map::*;
9#[cfg(creusot)]
10use std::{
11 default::Default,
12 hash::{BuildHasher, Hash},
13};
14
15#[cfg(feature = "nightly")]
16impl<K: DeepModel, V, S, A: Allocator> View for HashMap<K, V, S, A> {
17 type ViewTy = FMap<K::DeepModelTy, V>;
18
19 #[logic(opaque)]
20 fn view(self) -> Self::ViewTy {
21 dead
22 }
23}
24
25extern_spec! {
26 impl<K: DeepModel, V, S, A: Allocator> HashMap<K, V, S, A> {
27 #[ensures(self@ == result@)]
28 fn iter(&self) -> Iter<'_, K, V>;
29
30 #[ensures(forall<k: K::DeepModelTy> (*self)@.contains(k) == (^self)@.contains(k))]
31 #[ensures(forall<k: K::DeepModelTy> (*self)@.contains(k) == result@.contains(k))]
32 #[ensures(forall<k: K::DeepModelTy> (*self)@.contains(k) ==> (*self)@[k] == *result@[k] && (^self)@[k] == ^result@[k])]
33 fn iter_mut(&mut self) -> IterMut<'_, K, V>;
34 }
35
36 impl<K: DeepModel, V, S, A: Allocator> IntoIterator for HashMap<K, V, S, A> {
37 #[ensures(self@ == result@)]
38 fn into_iter(self) -> IntoIter<K, V, A>;
39 }
40
41 impl<'a, K: DeepModel, V, S, A: Allocator> IntoIterator for &'a HashMap<K, V, S, A> {
42 #[ensures(self@ == result@)]
43 fn into_iter(self) -> Iter<'a, K, V>;
44 }
45
46 impl<'a, K: DeepModel, V, S, A: Allocator> IntoIterator for &'a mut HashMap<K, V, S, A> {
47 #[ensures(forall<k: K::DeepModelTy> (*self)@.contains(k) == (^self)@.contains(k))]
48 #[ensures(forall<k: K::DeepModelTy> (*self)@.contains(k) == result@.contains(k))]
49 #[ensures(forall<k: K::DeepModelTy> (*self)@.contains(k) ==> (*self)@[k] == *result@[k] && (^self)@[k] == ^result@[k])]
50 fn into_iter(self) -> IterMut<'a, K, V>;
51 }
52
53 impl<K: Eq + Hash + DeepModel, V, S: BuildHasher + Default> FromIterator<(K, V)>
54 for HashMap<K, V, S>
55 {
56 #[requires(T::into_iter.precondition((iter,)))]
57 #[ensures(exists<into_iter: T::IntoIter, prod: Seq<(K, V)>, done: &mut T::IntoIter>
58 T::into_iter.postcondition((iter,), into_iter) &&
59 into_iter.produces(prod, *done) && done.completed() && resolve(^done) &&
60 forall<k: K::DeepModelTy, v: V> (result@.get(k) == Some(v))
61 == (exists<i, k1: K> 0 <= i && i < prod.len() && k1.deep_model() == k && prod[i] == (k1, v)
62 && forall<j> i < j && j < prod.len() ==> prod[j].0.deep_model() != k)
63 )]
64 fn from_iter<T: IntoIterator<Item = (K, V), IntoIter: IteratorSpec>>(iter: T) -> Self;
65 }
66}
67
68#[cfg(feature = "nightly")]
69impl<K: DeepModel, V, A: Allocator> View for IntoIter<K, V, A> {
70 type ViewTy = FMap<K::DeepModelTy, V>;
71
72 #[logic(opaque)]
73 fn view(self) -> Self::ViewTy {
74 dead
75 }
76}
77
78#[cfg(feature = "nightly")]
79impl<K: DeepModel, V, A: Allocator> IteratorSpec for IntoIter<K, V, A> {
80 #[logic(open, prophetic, inline)]
81 fn produces(self, visited: Seq<Self::Item>, o: Self) -> bool {
82 pearlite! {
84 self@.len() == visited.len() + o@.len()
85 && (forall<k: K, v: V> visited.contains((k, v))
86 ==> self@.get(k.deep_model()) == Some(v) && o@.get(k.deep_model()) == None)
87 && (forall<k: K::DeepModelTy, v: V> o@.get(k) == Some(v)
88 ==> self@.get(k) == Some(v) && !exists<k2: K, v2: V> k2.deep_model() == k && visited.contains((k2, v2)))
89 && (forall<k: K::DeepModelTy, v: V> self@.get(k) == Some(v)
90 ==> (exists<k1: K> k1.deep_model() == k && visited.contains((k1, v))) || o@.get(k) == Some(v))
91 && (forall<i1, i2>
92 0 <= i1 && i1 < visited.len() && 0 <= i2 && i2 < visited.len()
93 && visited[i1].0.deep_model() == visited[i2].0.deep_model()
94 ==> i1 == i2)
95 }
96 }
97
98 #[logic(open, prophetic)]
99 fn completed(&mut self) -> bool {
100 pearlite! { resolve(self) && self@.is_empty() }
101 }
102
103 #[logic(law)]
104 #[ensures(self.produces(Seq::empty(), self))]
105 fn produces_refl(self) {}
106
107 #[logic(law)]
108 #[requires(a.produces(ab, b))]
109 #[requires(b.produces(bc, c))]
110 #[ensures(a.produces(ab.concat(bc), c))]
111 fn produces_trans(a: Self, ab: Seq<Self::Item>, b: Self, bc: Seq<Self::Item>, c: Self) {
112 proof_assert! { forall<i> 0 <= i && i < bc.len() ==> bc[i] == ab.concat(bc)[ab.len() + i] }
113 }
114}
115
116extern_spec! {
117 impl<K: DeepModel, V, A: Allocator> Iterator for IntoIter<K, V, A> {
118 #[ensures(result.0@ == self@.len())]
119 #[ensures(result.1 == Some(result.0))]
120 fn size_hint(&self) -> (usize, Option<usize>);
121 }
122}
123
124#[cfg(feature = "nightly")]
125impl<K: DeepModel, V, A: Allocator> ExactSizeIteratorSpec for IntoIter<K, V, A> {
126 #[logic(law)]
127 #[requires(Self::size_hint.postcondition((self,), r))]
128 #[ensures(r.1 == Some(r.0))]
129 #[allow(unused_variables)]
130 fn size_hint_exact(&self, r: (usize, Option<usize>)) {}
131}
132
133impl<'a, K: DeepModel, V> View for Iter<'a, K, V> {
134 type ViewTy = FMap<K::DeepModelTy, V>;
135
136 #[logic(opaque)]
137 fn view(self) -> Self::ViewTy {
138 dead
139 }
140}
141
142impl<'a, K: DeepModel, V> IteratorSpec for Iter<'a, K, V> {
143 #[logic(open, prophetic, inline)]
144 fn produces(self, visited: Seq<Self::Item>, o: Self) -> bool {
145 pearlite! {
147 self@.len() == visited.len() + o@.len()
148 && (forall<k: &K, v: &V> visited.contains((k, v))
149 ==> self@.get(k.deep_model()) == Some(*v) && o@.get(k.deep_model()) == None)
150 && (forall<k: K::DeepModelTy, v: V> o@.get(k) == Some(v)
151 ==> self@.get(k) == Some(v) && !exists<k2: &K, v2: &V> k2.deep_model() == k && visited.contains((k2, v2)))
152 && (forall<k: K::DeepModelTy, v: V> self@.get(k) == Some(v)
153 ==> (exists<k2: &K> k2.deep_model() == k && visited.contains((k2, &v))) || o@.get(k) == Some(v))
154 && (forall<i1, i2>
155 0 <= i1 && i1 < visited.len() && 0 <= i2 && i2 < visited.len()
156 && visited[i1].0.deep_model() == visited[i2].0.deep_model()
157 ==> i1 == i2)
158 }
159 }
160
161 #[logic(open, prophetic)]
162 fn completed(&mut self) -> bool {
163 pearlite! { resolve(self) && self@.is_empty() }
164 }
165
166 #[logic(law)]
167 #[ensures(self.produces(Seq::empty(), self))]
168 fn produces_refl(self) {}
169
170 #[logic(law)]
171 #[requires(a.produces(ab, b))]
172 #[requires(b.produces(bc, c))]
173 #[ensures(a.produces(ab.concat(bc), c))]
174 fn produces_trans(a: Self, ab: Seq<Self::Item>, b: Self, bc: Seq<Self::Item>, c: Self) {
175 proof_assert! { forall<i> 0 <= i && i < bc.len() ==> bc[i] == ab.concat(bc)[ab.len() + i] }
176 }
177}
178
179extern_spec! {
180 impl<'a, K: DeepModel, V> Iterator for Iter<'a, K, V> {
181 #[ensures(result.0@ == self@.len())]
182 #[ensures(result.1 == Some(result.0))]
183 fn size_hint(&self) -> (usize, Option<usize>);
184 }
185}
186
187impl<'a, K: DeepModel, V> ExactSizeIteratorSpec for Iter<'a, K, V> {
188 #[logic(law)]
189 #[requires(Self::size_hint.postcondition((self,), r))]
190 #[ensures(r.1 == Some(r.0))]
191 #[allow(unused_variables)]
192 fn size_hint_exact(&self, r: (usize, Option<usize>)) {}
193}
194
195impl<'a, K: DeepModel, V> View for IterMut<'a, K, V> {
196 type ViewTy = FMap<K::DeepModelTy, &'a mut V>;
197
198 #[logic(opaque)]
199 fn view(self) -> Self::ViewTy {
200 dead
201 }
202}
203
204impl<'a, K: DeepModel, V> IteratorSpec for IterMut<'a, K, V> {
205 #[logic(open, prophetic, inline)]
206 fn produces(self, visited: Seq<Self::Item>, o: Self) -> bool {
207 pearlite! {
209 self@.len() == visited.len() + o@.len()
210 && (forall<k: K, v: &mut V> visited.contains((&k, v))
211 ==> self@.get(k.deep_model()) == Some(v) && o@.get(k.deep_model()) == None)
212 && (forall<k: K::DeepModelTy, v: &mut V> o@.get(k) == Some(v)
213 ==> self@.get(k) == Some(v) && !exists<k2: &K, v2: &mut V> k2.deep_model() == k && visited.contains((k2, v2)))
214 && (forall<k: K::DeepModelTy, v: &mut V> self@.get(k) == Some(v)
215 ==> (exists<k1: &K> k1.deep_model() == k && visited.contains((k1, v))) || o@.get(k) == Some(v))
216 && (forall<i1, i2>
217 0 <= i1 && i1 < visited.len() && 0 <= i2 && i2 < visited.len()
218 && visited[i1].0.deep_model() == visited[i2].0.deep_model()
219 ==> i1 == i2)
220 }
221 }
222
223 #[logic(open, prophetic)]
224 fn completed(&mut self) -> bool {
225 pearlite! { resolve(self) && self@.is_empty() }
226 }
227
228 #[logic(law)]
229 #[ensures(self.produces(Seq::empty(), self))]
230 fn produces_refl(self) {}
231
232 #[logic(law)]
233 #[requires(a.produces(ab, b))]
234 #[requires(b.produces(bc, c))]
235 #[ensures(a.produces(ab.concat(bc), c))]
236 fn produces_trans(a: Self, ab: Seq<Self::Item>, b: Self, bc: Seq<Self::Item>, c: Self) {
237 proof_assert! { forall<i> 0 <= i && i < bc.len() ==> bc[i] == ab.concat(bc)[ab.len() + i] }
238 }
239}
240
241extern_spec! {
242 impl<'a, K: DeepModel, V> Iterator for IterMut<'a, K, V> {
243 #[ensures(result.0@ == self@.len())]
244 #[ensures(result.1 == Some(result.0))]
245 fn size_hint(&self) -> (usize, Option<usize>);
246 }
247}
248
249impl<'a, K: DeepModel, V> ExactSizeIteratorSpec for IterMut<'a, K, V> {
250 #[logic(law)]
251 #[requires(Self::size_hint.postcondition((self,), r))]
252 #[ensures(r.1 == Some(r.0))]
253 #[allow(unused_variables)]
254 fn size_hint_exact(&self, r: (usize, Option<usize>)) {}
255}
256
257#[cfg(not(feature = "nightly"))]
258mod impls {
259 use crate::{logic::FMap, prelude::*, std::iter::ExactSizeIteratorSpec};
260 use std::collections::hash_map::{HashMap, IntoIter};
261
262 impl<K: DeepModel, V, S> View for HashMap<K, V, S> {
263 type ViewTy = FMap<K::DeepModelTy, V>;
264 }
265 impl<K: DeepModel, V> View for IntoIter<K, V> {
266 type ViewTy = FMap<K::DeepModelTy, V>;
267 }
268 impl<K: DeepModel, V> IteratorSpec for IntoIter<K, V> {}
269 impl<K: DeepModel, V> ExactSizeIteratorSpec for IntoIter<K, V> {}
270}