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