creusot_contracts/logic/seq.rs
1#[cfg(creusot)]
2use crate::resolve::structural_resolve;
3use crate::{
4 ghost::Plain,
5 logic::{Mapping, ops::IndexLogic},
6 prelude::*,
7 std::ops::RangeInclusiveExt as _,
8};
9use std::{
10 marker::PhantomData,
11 ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive},
12};
13
14/// A type of sequence usable in pearlite and `ghost!` blocks.
15///
16/// # Logic
17///
18/// This type is (in particular) the logical representation of a [`Vec`]. This can be
19/// accessed via its [view][crate::model::View] (The `@` operator).
20///
21/// ```rust,creusot
22/// # use creusot_contracts::prelude::*;
23/// #[logic]
24/// fn get_model<T>(v: Vec<T>) -> Seq<T> {
25/// pearlite!(v@)
26/// }
27/// ```
28///
29/// # Ghost
30///
31/// Since [`Vec`] have finite capacity, this could cause some issues in ghost code:
32/// ```rust,creusot,compile_fail
33/// ghost! {
34/// let mut v = Vec::new();
35/// for _ in 0..=usize::MAX as u128 + 1 {
36/// v.push(0); // cannot fail, since we are in a ghost block
37/// }
38/// proof_assert!(v@.len() <= usize::MAX@); // by definition
39/// proof_assert!(v@.len() > usize::MAX@); // uh-oh
40/// }
41/// ```
42///
43/// This type is designed for this use-case, with no restriction on the capacity.
44#[builtin("seq.Seq.seq")]
45pub struct Seq<T>(PhantomData<T>);
46
47/// Logical definitions
48impl<T> Seq<T> {
49 /// Returns the empty sequence.
50 #[logic]
51 #[builtin("seq.Seq.empty", ascription)]
52 pub fn empty() -> Self {
53 dead
54 }
55
56 /// Create a new sequence in pearlite.
57 ///
58 /// The new sequence will be of length `n`, and will contain `mapping[i]` at index `i`.
59 ///
60 /// # Example
61 ///
62 /// ```
63 /// # use creusot_contracts::prelude::*;
64 /// let s = snapshot!(Seq::create(5, |i| i + 1));
65 /// proof_assert!(s.len() == 5);
66 /// proof_assert!(forall<i> 0 <= i && i < 5 ==> s[i] == i + 1);
67 /// ```
68 #[logic]
69 #[builtin("seq.Seq.create")]
70 pub fn create(n: Int, mapping: Mapping<Int, T>) -> Self {
71 let _ = n;
72 let _ = mapping;
73 dead
74 }
75
76 /// Returns the value at index `ix`.
77 ///
78 /// If `ix` is out of bounds, return `None`.
79 #[logic(open)]
80 pub fn get(self, ix: Int) -> Option<T> {
81 if 0 <= ix && ix < self.len() { Some(self.index_logic(ix)) } else { None }
82 }
83
84 /// Returns the value at index `ix`.
85 ///
86 /// If `ix` is out of bounds, the returned value is meaningless.
87 ///
88 /// You should prefer using the indexing operator `s[ix]`.
89 ///
90 /// # Example
91 ///
92 /// ```
93 /// # use creusot_contracts::prelude::*;
94 /// let s = snapshot!(Seq::singleton(2));
95 /// proof_assert!(s.index_logic_unsized(0) == 2);
96 /// proof_assert!(s[0] == 2); // prefer this
97 /// ```
98 #[logic]
99 #[builtin("seq.Seq.get")]
100 pub fn index_logic_unsized(self, ix: Int) -> Box<T> {
101 let _ = ix;
102 dead
103 }
104
105 /// Returns the subsequence between indices `start` and `end`.
106 ///
107 /// If either `start` or `end` are out of bounds, the result is meaningless.
108 ///
109 /// # Example
110 ///
111 /// ```
112 /// # use creusot_contracts::prelude::*;
113 /// let subs = snapshot! {
114 /// let s: Seq<Int> = Seq::create(10, |i| i);
115 /// s.subsequence(2, 5)
116 /// };
117 /// proof_assert!(subs.len() == 3);
118 /// proof_assert!(subs[0] == 2 && subs[1] == 3 && subs[2] == 4);
119 /// ```
120 #[logic]
121 #[builtin("seq.Seq.([..])")]
122 pub fn subsequence(self, start: Int, end: Int) -> Self {
123 let _ = start;
124 let _ = end;
125 dead
126 }
127
128 /// Create a sequence containing one element.
129 ///
130 /// # Example
131 ///
132 /// ```
133 /// # use creusot_contracts::prelude::*;
134 /// let s = snapshot!(Seq::singleton(42));
135 /// proof_assert!(s.len() == 1);
136 /// proof_assert!(s[0] == 42);
137 /// ```
138 #[logic]
139 #[builtin("seq.Seq.singleton")]
140 pub fn singleton(value: T) -> Self {
141 let _ = value;
142 dead
143 }
144
145 /// Returns the sequence without its first element.
146 ///
147 /// If the sequence is empty, the result is meaningless.
148 ///
149 /// # Example
150 ///
151 /// ```
152 /// # use creusot_contracts::prelude::*;
153 /// let s = snapshot!(seq![5, 10, 15]);
154 /// proof_assert!(s.tail() == seq![10, 15]);
155 /// proof_assert!(s.tail().tail() == Seq::singleton(15));
156 /// proof_assert!(s.tail().tail().tail() == Seq::empty());
157 /// ```
158 #[logic(open)]
159 pub fn tail(self) -> Self {
160 self.subsequence(1, self.len())
161 }
162
163 /// Alias for [`Self::tail`].
164 #[logic(open)]
165 pub fn pop_front(self) -> Self {
166 self.tail()
167 }
168
169 /// Returns the sequence without its last element.
170 ///
171 /// If the sequence is empty, the result is meaningless.
172 ///
173 /// # Example
174 ///
175 /// ```
176 /// # use creusot_contracts::prelude::*;
177 /// let s = snapshot!(seq![5, 10, 15]);
178 /// proof_assert!(s.pop_back() == seq![5, 10]);
179 /// proof_assert!(s.pop_back().pop_back() == Seq::singleton(5));
180 /// proof_assert!(s.pop_back().pop_back().pop_back() == Seq::empty());
181 /// ```
182 #[logic(open)]
183 pub fn pop_back(self) -> Self {
184 self.subsequence(0, self.len() - 1)
185 }
186
187 /// Returns the number of elements in the sequence, also referred to as its 'length'.
188 ///
189 /// # Example
190 ///
191 /// ```
192 /// # use creusot_contracts::prelude::*;
193 /// #[requires(v@.len() > 0)]
194 /// fn f<T>(v: Vec<T>) { /* ... */ }
195 /// ```
196 #[logic]
197 #[builtin("seq.Seq.length")]
198 pub fn len(self) -> Int {
199 dead
200 }
201
202 /// Returns a new sequence, where the element at index `ix` has been replaced by `x`.
203 ///
204 /// If `ix` is out of bounds, the result is meaningless.
205 ///
206 /// # Example
207 ///
208 /// ```
209 /// # use creusot_contracts::prelude::*;
210 /// let s = snapshot!(Seq::create(2, |_| 0));
211 /// let s2 = snapshot!(s.set(1, 3));
212 /// proof_assert!(s2[0] == 0);
213 /// proof_assert!(s2[1] == 3);
214 /// ```
215 #[logic]
216 #[builtin("seq.Seq.set")]
217 pub fn set(self, ix: Int, x: T) -> Self {
218 let _ = ix;
219 let _ = x;
220 dead
221 }
222
223 /// Extensional equality
224 ///
225 /// Returns `true` if `self` and `other` have the same length, and contain the same
226 /// elements at the same indices.
227 ///
228 /// This is in fact equivalent with normal equality.
229 #[logic]
230 #[builtin("seq.Seq.(==)")]
231 pub fn ext_eq(self, other: Self) -> bool {
232 let _ = other;
233 dead
234 }
235
236 // internal wrapper to match the order of arguments of Seq.cons
237 #[doc(hidden)]
238 #[logic]
239 #[builtin("seq.Seq.cons")]
240 pub fn cons(_: T, _: Self) -> Self {
241 dead
242 }
243
244 /// Returns a new sequence, where `x` has been prepended to `self`.
245 ///
246 /// # Example
247 ///
248 /// ```
249 /// let s = snapshot!(Seq::singleton(1));
250 /// let s2 = snapshot!(s.push_front(2));
251 /// proof_assert!(s2[0] == 2);
252 /// proof_assert!(s2[1] == 1);
253 /// ```
254 #[logic(open, inline)]
255 pub fn push_front(self, x: T) -> Self {
256 Self::cons(x, self)
257 }
258
259 /// Returns a new sequence, where `x` has been appended to `self`.
260 ///
261 /// # Example
262 ///
263 /// ```
264 /// let s = snapshot!(Seq::singleton(1));
265 /// let s2 = snapshot!(s.push_back(2));
266 /// proof_assert!(s2[0] == 1);
267 /// proof_assert!(s2[1] == 2);
268 /// ```
269 #[logic]
270 #[builtin("seq.Seq.snoc")]
271 pub fn push_back(self, x: T) -> Self {
272 let _ = x;
273 dead
274 }
275
276 /// Returns a new sequence, made of the concatenation of `self` and `other`.
277 ///
278 /// # Example
279 ///
280 /// ```
281 /// # use creusot_contracts::prelude::*;
282 /// let s1 = snapshot!(Seq::singleton(1));
283 /// let s2 = snapshot!(Seq::create(2, |i| i));
284 /// let s = snapshot!(s1.concat(s2));
285 /// proof_assert!(s[0] == 1);
286 /// proof_assert!(s[1] == 0);
287 /// proof_assert!(s[2] == 1);
288 /// ```
289 #[logic]
290 #[builtin("seq.Seq.(++)")]
291 pub fn concat(self, other: Self) -> Self {
292 let _ = other;
293 dead
294 }
295
296 #[logic]
297 #[ensures(result.len() == self.len())]
298 #[ensures(forall<i> 0 <= i && i < self.len() ==> result[i] == m[self[i]])]
299 #[variant(self.len())]
300 pub fn map<U>(self, m: Mapping<T, U>) -> Seq<U> {
301 if self.len() == 0 {
302 Seq::empty()
303 } else {
304 self.tail().map(m).push_front(m.get(*self.index_logic_unsized(0)))
305 }
306 }
307
308 #[logic(open)]
309 #[variant(self.len())]
310 pub fn flat_map<U>(self, other: Mapping<T, Seq<U>>) -> Seq<U> {
311 if self.len() == 0 {
312 Seq::empty()
313 } else {
314 other.get(*self.index_logic_unsized(0)).concat(self.tail().flat_map(other))
315 }
316 }
317
318 /// Returns a new sequence, which is `self` in reverse order.
319 ///
320 /// # Example
321 ///
322 /// ```
323 /// # use creusot_contracts::prelude::*;
324 /// let s = snapshot!(Seq::create(3, |i| i));
325 /// let s2 = snapshot!(s.reverse());
326 /// proof_assert!(s2[0] == 2);
327 /// proof_assert!(s2[1] == 1);
328 /// proof_assert!(s2[2] == 0);
329 /// ```
330 #[logic]
331 #[builtin("seq.Reverse.reverse")]
332 pub fn reverse(self) -> Self {
333 dead
334 }
335
336 /// Returns `true` if `other` is a permutation of `self`.
337 #[logic(open)]
338 pub fn permutation_of(self, other: Self) -> bool {
339 self.permut(other, 0, self.len())
340 }
341
342 /// Returns `true` if:
343 /// - `self` and `other` have the same length
344 /// - `start` and `end` are in bounds (between `0` and `self.len()` included)
345 /// - Every element of `self` between `start` (included) and `end` (excluded) can
346 /// also be found in `other` between `start` and `end`, and vice-versa
347 #[logic]
348 #[builtin("seq.Permut.permut")]
349 pub fn permut(self, other: Self, start: Int, end: Int) -> bool {
350 let _ = other;
351 let _ = start;
352 let _ = end;
353 dead
354 }
355
356 /// Returns `true` if:
357 /// - `self` and `other` have the same length
358 /// - `i` and `j` are in bounds (between `0` and `self.len()` excluded)
359 /// - `other` is equal to `self` where the elements at `i` and `j` are swapped
360 #[logic]
361 #[builtin("seq.Permut.exchange")]
362 pub fn exchange(self, other: Self, i: Int, j: Int) -> bool {
363 let _ = other;
364 let _ = i;
365 let _ = j;
366 dead
367 }
368
369 /// Returns `true` if there is an index `i` such that `self[i] == x`.
370 #[logic(open)]
371 pub fn contains(self, x: T) -> bool {
372 pearlite! { exists<i> 0 <= i && i < self.len() && self[i] == x }
373 }
374
375 /// Returns `true` if `self` is sorted between `start` and `end`.
376 #[logic(open)]
377 pub fn sorted_range(self, start: Int, end: Int) -> bool
378 where
379 T: OrdLogic,
380 {
381 pearlite! {
382 forall<i, j> start <= i && i <= j && j < end ==> self[i] <= self[j]
383 }
384 }
385
386 /// Returns `true` if `self` is sorted.
387 #[logic(open)]
388 pub fn sorted(self) -> bool
389 where
390 T: OrdLogic,
391 {
392 self.sorted_range(0, self.len())
393 }
394
395 #[logic(open)]
396 #[ensures(forall<a: Seq<T>, b: Seq<T>, x>
397 a.concat(b).contains(x) == a.contains(x) || b.contains(x))]
398 pub fn concat_contains() {}
399}
400
401impl<T> Seq<Seq<T>> {
402 #[logic(open)]
403 #[variant(self.len())]
404 pub fn flatten(self) -> Seq<T> {
405 if self.len() == 0 {
406 Seq::empty()
407 } else {
408 self.index_logic_unsized(0).concat(self.tail().flatten())
409 }
410 }
411}
412
413impl<T> Seq<&T> {
414 /// Convert `Seq<&T>` to `Seq<T>`.
415 ///
416 /// This is simply a utility method, because `&T` is equivalent to `T` in pearlite.
417 #[logic]
418 #[builtin("identity")]
419 pub fn to_owned_seq(self) -> Seq<T> {
420 dead
421 }
422}
423
424impl<T> IndexLogic<Int> for Seq<T> {
425 type Item = T;
426
427 #[logic]
428 #[builtin("seq.Seq.get")]
429 fn index_logic(self, _: Int) -> Self::Item {
430 dead
431 }
432}
433
434impl<T> IndexLogic<Range<Int>> for Seq<T> {
435 type Item = Seq<T>;
436
437 #[logic(open, inline)]
438 fn index_logic(self, range: Range<Int>) -> Self::Item {
439 self.subsequence(range.start, range.end)
440 }
441}
442
443impl<T> IndexLogic<RangeInclusive<Int>> for Seq<T> {
444 type Item = Seq<T>;
445
446 #[logic(open, inline)]
447 fn index_logic(self, range: RangeInclusive<Int>) -> Self::Item {
448 self.subsequence(range.start_log(), range.end_log() + 1)
449 }
450}
451
452impl<T> IndexLogic<RangeFull> for Seq<T> {
453 type Item = Seq<T>;
454
455 #[logic(open, inline)]
456 fn index_logic(self, _: RangeFull) -> Self::Item {
457 self
458 }
459}
460
461impl<T> IndexLogic<RangeFrom<Int>> for Seq<T> {
462 type Item = Seq<T>;
463
464 #[logic(open, inline)]
465 fn index_logic(self, range: RangeFrom<Int>) -> Self::Item {
466 self.subsequence(range.start, self.len())
467 }
468}
469
470impl<T> IndexLogic<RangeTo<Int>> for Seq<T> {
471 type Item = Seq<T>;
472
473 #[logic(open, inline)]
474 fn index_logic(self, range: RangeTo<Int>) -> Self::Item {
475 self.subsequence(0, range.end)
476 }
477}
478
479impl<T> IndexLogic<RangeToInclusive<Int>> for Seq<T> {
480 type Item = Seq<T>;
481
482 #[logic(open, inline)]
483 fn index_logic(self, range: RangeToInclusive<Int>) -> Self::Item {
484 self.subsequence(0, range.end + 1)
485 }
486}
487
488/// Ghost definitions
489impl<T> Seq<T> {
490 /// Constructs a new, empty `Seq<T>`.
491 ///
492 /// This can only be manipulated in the ghost world, and as such is wrapped in [`Ghost`].
493 ///
494 /// # Example
495 ///
496 /// ```rust,creusot
497 /// use creusot_contracts::prelude::*;
498 /// let ghost_seq = Seq::<i32>::new();
499 /// proof_assert!(seq == Seq::create());
500 /// ```
501 #[trusted]
502 #[check(ghost)]
503 #[ensures(*result == Self::empty())]
504 #[allow(unreachable_code)]
505 pub fn new() -> Ghost<Self> {
506 Ghost::conjure()
507 }
508
509 /// Returns the number of elements in the sequence, also referred to as its 'length'.
510 ///
511 /// If you need to get the length in pearlite, consider using [`len`](Self::len).
512 ///
513 /// # Example
514 /// ```rust,creusot
515 /// use creusot_contracts::prelude::*;
516 ///
517 /// let mut s = Seq::new();
518 /// ghost! {
519 /// s.push_back_ghost(1);
520 /// s.push_back_ghost(2);
521 /// s.push_back_ghost(3);
522 /// let len = s.len_ghost();
523 /// proof_assert!(len == 3);
524 /// };
525 /// ```
526 #[trusted]
527 #[check(ghost)]
528 #[ensures(result == self.len())]
529 pub fn len_ghost(&self) -> Int {
530 panic!()
531 }
532
533 /// Returns `true` if the sequence is empty.
534 ///
535 /// # Example
536 ///
537 /// ```rust,creusot
538 /// use creusot_contracts::prelude::*;
539 /// #[check(ghost)]
540 /// #[requires(s.len() == 0)]
541 /// pub fn foo(mut s: Seq<i32>) {
542 /// assert!(s.is_empty_ghost());
543 /// s.push_back_ghost(1i32);
544 /// assert!(!s.is_empty_ghost());
545 /// }
546 /// ghost! {
547 /// foo(Seq::new().into_inner())
548 /// };
549 /// ```
550 #[trusted]
551 #[check(ghost)]
552 #[ensures(result == (self.len() == 0))]
553 pub fn is_empty_ghost(&self) -> bool {
554 panic!()
555 }
556
557 /// Appends an element to the front of a collection.
558 ///
559 /// # Example
560 /// ```rust,creusot
561 /// use creusot_contracts::prelude::*;
562 ///
563 /// let mut s = Seq::new();
564 /// ghost! {
565 /// s.push_front_ghost(1);
566 /// s.push_front_ghost(2);
567 /// s.push_front_ghost(3);
568 /// proof_assert!(s[0] == 3i32 && s[1] == 2i32 && s[2] == 1i32);
569 /// };
570 /// ```
571 #[trusted]
572 #[check(ghost)]
573 #[ensures(^self == self.push_front(x))]
574 pub fn push_front_ghost(&mut self, x: T) {
575 let _ = x;
576 panic!()
577 }
578
579 /// Appends an element to the back of a collection.
580 ///
581 /// # Example
582 /// ```rust,creusot
583 /// use creusot_contracts::prelude::*;
584 ///
585 /// let mut s = Seq::new();
586 /// ghost! {
587 /// s.push_back_ghost(1);
588 /// s.push_back_ghost(2);
589 /// s.push_back_ghost(3);
590 /// proof_assert!(s[0] == 1i32 && s[1] == 2i32 && s[2] == 3i32);
591 /// };
592 /// ```
593 #[trusted]
594 #[check(ghost)]
595 #[ensures(^self == self.push_back(x))]
596 pub fn push_back_ghost(&mut self, x: T) {
597 let _ = x;
598 panic!()
599 }
600
601 /// Returns a reference to an element at `index` or `None` if `index` is out of bounds.
602 ///
603 /// # Example
604 /// ```rust,creusot
605 /// use creusot_contracts::prelude::*;
606 ///
607 /// let mut s = Seq::new();
608 /// ghost! {
609 /// s.push_back_ghost(10);
610 /// s.push_back_ghost(40);
611 /// s.push_back_ghost(30);
612 /// let get1 = s.get_ghost(1int);
613 /// let get2 = s.get_ghost(3int);
614 /// proof_assert!(get1 == Some(&40i32));
615 /// proof_assert!(get2 == None);
616 /// };
617 /// ```
618 #[trusted]
619 #[check(ghost)]
620 #[ensures(match self.get(index) {
621 None => result == None,
622 Some(v) => result == Some(&v),
623 })]
624 pub fn get_ghost(&self, index: Int) -> Option<&T> {
625 let _ = index;
626 panic!()
627 }
628
629 /// Returns a mutable reference to an element at `index` or `None` if `index` is out of bounds.
630 ///
631 /// # Example
632 /// ```rust,creusot
633 /// use creusot_contracts::prelude::*;
634 ///
635 /// let mut s = Seq::new();
636 ///
637 /// ghost! {
638 /// s.push_back_ghost(0);
639 /// s.push_back_ghost(1);
640 /// s.push_back_ghost(2);
641 /// if let Some(elem) = s.get_mut_ghost(1int) {
642 /// *elem = 42;
643 /// }
644 /// proof_assert!(s[0] == 0i32 && s[1] == 42i32 && s[2] == 2i32);
645 /// };
646 /// ```
647 #[trusted]
648 #[check(ghost)]
649 #[ensures(match result {
650 None => self.get(index) == None && *self == ^self,
651 Some(r) => self.get(index) == Some(*r) && ^r == (^self)[index],
652 })]
653 #[ensures(forall<i> i != index ==> (*self).get(i) == (^self).get(i))]
654 #[ensures((*self).len() == (^self).len())]
655 pub fn get_mut_ghost(&mut self, index: Int) -> Option<&mut T> {
656 let _ = index;
657 panic!()
658 }
659
660 /// Removes the last element from a vector and returns it, or `None` if it is empty.
661 ///
662 /// # Example
663 /// ```rust,creusot
664 /// use creusot_contracts::prelude::*;
665 ///
666 /// let mut s = Seq::new();
667 /// ghost! {
668 /// s.push_back_ghost(1);
669 /// s.push_back_ghost(2);
670 /// s.push_back_ghost(3);
671 /// let popped = s.pop_back_ghost();
672 /// proof_assert!(popped == Some(3i32));
673 /// proof_assert!(s[0] == 1i32 && s[1] == 2i32);
674 /// };
675 /// ```
676 #[trusted]
677 #[check(ghost)]
678 #[ensures(match result {
679 None => *self == Seq::empty() && *self == ^self,
680 Some(r) => *self == (^self).push_back(r)
681 })]
682 pub fn pop_back_ghost(&mut self) -> Option<T> {
683 panic!()
684 }
685
686 /// Removes the first element from a vector and returns it, or `None` if it is empty.
687 ///
688 /// # Example
689 /// ```rust,creusot
690 /// use creusot_contracts::prelude::*;
691 ///
692 /// let mut s = Seq::new();
693 /// ghost! {
694 /// s.push_back_ghost(1);
695 /// s.push_back_ghost(2);
696 /// s.push_back_ghost(3);
697 /// let popped = s.pop_front_ghost();
698 /// proof_assert!(popped == Some(1i32));
699 /// proof_assert!(s[0] == 2i32 && s[1] == 3i32);
700 /// };
701 /// ```
702 #[trusted]
703 #[check(ghost)]
704 #[ensures(match result {
705 None => *self == Seq::empty() && *self == ^self,
706 Some(r) => (*self).len() > 0 && r == (*self)[0] && ^self == (*self).tail()
707 })]
708 pub fn pop_front_ghost(&mut self) -> Option<T> {
709 panic!()
710 }
711
712 /// Clears the sequence, removing all values.
713 ///
714 /// # Example
715 /// ```rust,creusot
716 /// use creusot_contracts::prelude::*;
717 ///
718 /// let mut s = Seq::new();
719 /// ghost! {
720 /// s.push_back_ghost(1);
721 /// s.push_back_ghost(2);
722 /// s.push_back_ghost(3);
723 /// s.clear_ghost();
724 /// proof_assert!(s == Seq::empty());
725 /// };
726 /// ```
727 #[trusted]
728 #[check(ghost)]
729 #[ensures(^self == Self::empty())]
730 pub fn clear_ghost(&mut self) {}
731
732 /// Split a sequence in two at the given index.
733 #[trusted]
734 #[check(ghost)]
735 #[requires(0 <= mid && mid <= self.len())]
736 #[ensures((^self).len() == mid)]
737 #[ensures((^self).concat(result) == *self)]
738 pub fn split_off_ghost(&mut self, mid: Int) -> Self {
739 let _ = mid;
740 panic!("ghost code")
741 }
742}
743
744impl<T> std::ops::Index<Int> for Seq<T> {
745 type Output = T;
746
747 #[check(ghost)]
748 #[requires(0 <= index && index < self.len())]
749 #[ensures(*result == self[index])]
750 fn index(&self, index: Int) -> &Self::Output {
751 self.get_ghost(index).unwrap()
752 }
753}
754impl<T> std::ops::IndexMut<Int> for Seq<T> {
755 #[check(ghost)]
756 #[requires(0 <= index && index < self.len())]
757 #[ensures((*self).len() == (^self).len())]
758 #[ensures(*result == (*self)[index] && ^result == (^self)[index])]
759 #[ensures(forall<i> i != index ==> (*self).get(i) == (^self).get(i))]
760 fn index_mut(&mut self, index: Int) -> &mut Self::Output {
761 self.get_mut_ghost(index).unwrap()
762 }
763}
764
765impl<T> std::ops::Index<(Int, Int)> for Seq<T> {
766 type Output = (T, T);
767
768 #[trusted]
769 #[check(ghost)]
770 #[requires(0 <= index.0 && index.0 < self.len() && 0 <= index.1 && index.1 < self.len())]
771 #[ensures(result.0 == self[index.0] && result.1 == self[index.1])]
772 #[allow(unused_variables)]
773 fn index(&self, index: (Int, Int)) -> &Self::Output {
774 panic!()
775 }
776}
777
778impl<T> std::ops::IndexMut<(Int, Int)> for Seq<T> {
779 #[trusted]
780 #[check(ghost)]
781 #[requires(0 <= index.0 && index.0 < self.len() && 0 <= index.1 && index.1 < self.len())]
782 #[requires(index.0 != index.1)]
783 #[ensures((*result).0 == (*self)[index.0] && (*result).1 == (*self)[index.1]
784 && (^result).0 == (^self)[index.0] && (^result).1 == (^self)[index.1])]
785 #[ensures(forall<i> i != index.0 && i != index.1 ==> (*self).get(i) == (^self).get(i))]
786 #[ensures((*self).len() == (^self).len())]
787 #[allow(unused_variables)]
788 fn index_mut(&mut self, index: (Int, Int)) -> &mut Self::Output {
789 panic!()
790 }
791}
792
793// Having `Copy` guarantees that the operation is pure, even if we decide to change the definition of `Clone`.
794impl<T: Clone + Copy> Clone for Seq<T> {
795 #[trusted]
796 #[check(ghost)]
797 #[ensures(result == *self)]
798 fn clone(&self) -> Self {
799 *self
800 }
801}
802
803impl<T: Copy> Copy for Seq<T> {}
804#[trusted]
805impl<T: Plain> Plain for Seq<T> {}
806
807impl<T> Invariant for Seq<T> {
808 #[logic(open, prophetic, inline)]
809 #[creusot::trusted_trivial_if_param_trivial]
810 fn invariant(self) -> bool {
811 pearlite! { forall<i> 0 <= i && i < self.len() ==> inv(self.index_logic_unsized(i)) }
812 }
813}
814
815// =========
816// Iterators
817// =========
818
819impl<T> IntoIterator for Seq<T> {
820 type Item = T;
821 type IntoIter = SeqIter<T>;
822
823 #[check(ghost)]
824 #[ensures(result@ == self)]
825 fn into_iter(self) -> SeqIter<T> {
826 SeqIter { inner: self }
827 }
828}
829
830/// An owning iterator for [`Seq`].
831///
832/// # Ghost code and variants
833///
834/// This iterator is only obtainable in ghost code.
835///
836/// To use it in a `for` loop, a variant must be declared:
837/// ```rust,creusot
838/// # use creusot_contracts::prelude::*;
839/// # #[requires(true)]
840/// fn iter_on_seq<T>(s: Seq<T>) {
841/// let len = snapshot!(s.len());
842/// #[variant(len - produced.len())]
843/// for i in s {
844/// // ...
845/// }
846/// }
847/// ```
848pub struct SeqIter<T> {
849 inner: Seq<T>,
850}
851
852impl<T> View for SeqIter<T> {
853 type ViewTy = Seq<T>;
854 #[logic]
855 fn view(self) -> Seq<T> {
856 self.inner
857 }
858}
859
860impl<T> Iterator for SeqIter<T> {
861 type Item = T;
862
863 #[check(ghost)]
864 #[ensures(match result {
865 None => self.completed(),
866 Some(v) => (*self).produces(Seq::singleton(v), ^self)
867 })]
868 fn next(&mut self) -> Option<T> {
869 self.inner.pop_front_ghost()
870 }
871}
872
873impl<T> IteratorSpec for SeqIter<T> {
874 #[logic(prophetic, open)]
875 fn produces(self, visited: Seq<T>, o: Self) -> bool {
876 pearlite! { self@ == visited.concat(o@) }
877 }
878
879 #[logic(prophetic, open)]
880 fn completed(&mut self) -> bool {
881 pearlite! { self@ == Seq::empty() }
882 }
883
884 #[logic(law)]
885 #[ensures(self.produces(Seq::empty(), self))]
886 fn produces_refl(self) {}
887
888 #[logic(law)]
889 #[requires(a.produces(ab, b))]
890 #[requires(b.produces(bc, c))]
891 #[ensures(a.produces(ab.concat(bc), c))]
892 fn produces_trans(a: Self, ab: Seq<Self::Item>, b: Self, bc: Seq<Self::Item>, c: Self) {}
893}
894
895impl<'a, T> IntoIterator for &'a Seq<T> {
896 type Item = &'a T;
897 type IntoIter = SeqIterRef<'a, T>;
898
899 #[check(ghost)]
900 #[ensures(result@ == *self)]
901 fn into_iter(self) -> Self::IntoIter {
902 SeqIterRef { inner: self, index: self.len_ghost() - self.len_ghost() }
903 }
904}
905
906/// An iterator over references in a [`Seq`].
907pub struct SeqIterRef<'a, T> {
908 inner: &'a Seq<T>,
909 index: Int,
910}
911impl<T> Invariant for SeqIterRef<'_, T> {
912 #[logic]
913 fn invariant(self) -> bool {
914 0 <= self.index && self.index <= self.inner.len()
915 }
916}
917
918impl<T> View for SeqIterRef<'_, T> {
919 type ViewTy = Seq<T>;
920 #[logic]
921 fn view(self) -> Seq<T> {
922 self.inner.subsequence(self.index, self.inner.len())
923 }
924}
925
926impl<'a, T> Iterator for SeqIterRef<'a, T> {
927 type Item = &'a T;
928
929 #[check(ghost)]
930 #[ensures(match result {
931 None => self.completed(),
932 Some(v) => (*self).produces(Seq::singleton(v), ^self)
933 })]
934 fn next(&mut self) -> Option<&'a T> {
935 let _before = snapshot!((*self)@);
936 if let Some(res) = self.inner.get_ghost(self.index) {
937 self.index.incr_ghost();
938 proof_assert!((*self)@ == _before.tail());
939 Some(res)
940 } else {
941 proof_assert!(self.index == self.inner.len());
942 proof_assert!(self@ == Seq::empty());
943 None
944 }
945 }
946}
947impl<'a, T> IteratorSpec for SeqIterRef<'a, T> {
948 #[logic(prophetic, open)]
949 fn produces(self, visited: Seq<&'a T>, o: Self) -> bool {
950 let visited: Seq<T> = visited.to_owned_seq();
951 pearlite! { self@ == visited.concat(o@) }
952 }
953
954 #[logic(prophetic, open)]
955 fn completed(&mut self) -> bool {
956 pearlite! { self@ == Seq::empty() }
957 }
958
959 #[logic(law)]
960 #[ensures(self.produces(Seq::empty(), self))]
961 fn produces_refl(self) {}
962
963 #[logic(law)]
964 #[requires(a.produces(ab, b))]
965 #[requires(b.produces(bc, c))]
966 #[ensures(a.produces(ab.concat(bc), c))]
967 fn produces_trans(a: Self, ab: Seq<Self::Item>, b: Self, bc: Seq<Self::Item>, c: Self) {}
968}
969
970impl<T> Resolve for Seq<T> {
971 #[logic(open, prophetic)]
972 #[creusot::trusted_trivial_if_param_trivial]
973 fn resolve(self) -> bool {
974 pearlite! { forall<i : Int> resolve(self.get(i)) }
975 }
976
977 #[trusted]
978 #[logic(open(self), prophetic)]
979 #[requires(structural_resolve(self))]
980 #[ensures(self.resolve())]
981 fn resolve_coherence(self) {}
982}
983
984impl<T> Resolve for SeqIter<T> {
985 #[logic(open, prophetic, inline)]
986 #[creusot::trusted_trivial_if_param_trivial]
987 fn resolve(self) -> bool {
988 pearlite! { resolve(self@) }
989 }
990
991 #[logic(open, prophetic)]
992 #[requires(structural_resolve(self))]
993 #[ensures(self.resolve())]
994 fn resolve_coherence(self) {}
995}
996
997// Some properties
998// TODO : use parameters instead of quantification, and mode to impl block
999
1000#[logic(open)]
1001#[ensures(forall<x: A, f: Mapping<A, Seq<B>>> Seq::singleton(x).flat_map(f) == f.get(x))]
1002pub fn flat_map_singleton<A, B>() {}
1003
1004#[logic(open)]
1005#[ensures(forall<x: A, f: Mapping<A, Seq<B>>> xs.push_back(x).flat_map(f) == xs.flat_map(f).concat(f.get(x)))]
1006#[variant(xs.len())]
1007pub fn flat_map_push_back<A, B>(xs: Seq<A>) {
1008 if xs.len() > 0 {
1009 flat_map_push_back::<A, B>(xs.tail());
1010 proof_assert! { forall<x: A> xs.tail().push_back(x) == xs.push_back(x).tail() }
1011 }
1012}