1use core::marker;
2
3#[allow(unused_imports)]
4use super::pervasive::*;
5#[allow(unused_imports)]
6use super::prelude::*;
7
8verus! {
9
10#[verifier::ext_equal]
11#[verifier::accept_recursive_types(A)]
12tracked enum SeqInner<A> {
13 Nil,
14 Cons { head: A, tail: Ghost<SeqInner<A>> },
15}
16
17impl<A> SeqInner<A> {
22 spec fn len(self) -> nat
23 decreases self,
24 {
25 match self {
26 SeqInner::Nil => 0,
27 SeqInner::Cons { tail, .. } => { 1 + tail.len() },
28 }
29 }
30
31 spec fn index(self, i: int) -> A
32 recommends
33 0 <= i < self.len(),
34 decreases self.len(),
35 {
36 match self {
37 SeqInner::Nil => arbitrary(),
38 SeqInner::Cons { head, tail } => if i == 0 {
39 head
40 } else {
41 tail.index(i - 1)
42 },
43 }
44 }
45
46 #[verifier::inline]
47 spec fn spec_index(self, i: int) -> A
48 recommends
49 0 <= i < self.len(),
50 {
51 self.index(i)
52 }
53
54 spec fn push(self, a: A) -> SeqInner<A>
55 decreases self.len(),
56 {
57 match self {
58 SeqInner::Nil => SeqInner::Cons { head: a, tail: Ghost(SeqInner::Nil) },
59 SeqInner::Cons { head, tail } => {
60 let new_tail = tail.push(a);
61 SeqInner::Cons { head, tail: Ghost(new_tail) }
62 },
63 }
64 }
65
66 spec fn update(self, i: int, a: A) -> SeqInner<A>
67 recommends
68 0 <= i < self.len(),
69 decreases self.len(),
70 {
71 if !(0 <= i < self.len()) { self
73 } else {
74 match self {
75 SeqInner::Nil => arbitrary(),
76 SeqInner::Cons { head, tail } => if i == 0 {
77 SeqInner::Cons { head: a, tail }
78 } else {
79 let new_tail = tail.update(i - 1, a);
80 SeqInner::Cons { head, tail: Ghost(new_tail) }
81 },
82 }
83 }
84 }
85
86 spec fn subrange(self, start_inclusive: int, end_exclusive: int) -> SeqInner<A>
87 recommends
88 0 <= start_inclusive <= end_exclusive <= self.len(),
89 decreases start_inclusive, end_exclusive - start_inclusive,
90 {
91 match self {
92 SeqInner::Nil => SeqInner::Nil,
93 SeqInner::Cons {
94 head,
95 tail,
96 } =>
97 if start_inclusive > 0 {
99 tail.subrange(start_inclusive - 1, end_exclusive - 1)
100 } else {
101 if end_exclusive <= 0 {
102 SeqInner::Nil
103 } else {
104 let new_tail = tail.subrange(start_inclusive, end_exclusive - 1);
105 SeqInner::Cons { head, tail: Ghost(new_tail) }
106 }
107 },
108 }
109 }
110
111 spec fn add(self, rhs: SeqInner<A>) -> SeqInner<A>
112 decreases self.len(),
113 {
114 match self {
115 SeqInner::Nil => rhs,
116 SeqInner::Cons { head, tail } => {
117 let new_tail = tail.add(rhs);
118 SeqInner::Cons { head, tail: Ghost(new_tail) }
119 },
120 }
121 }
122}
123
124#[verifier::ext_equal]
143#[verifier::accept_recursive_types(A)]
144pub tracked struct Seq<A> {
145 inner: SeqInner<A>,
146}
147
148impl<A> Seq<A> {
149 #[rustc_diagnostic_item = "verus::vstd::seq::Seq::empty"]
151 pub closed spec fn empty() -> Seq<A> {
152 Seq { inner: SeqInner::Nil }
153 }
154
155 #[rustc_diagnostic_item = "verus::vstd::seq::Seq::new"]
157 pub closed spec fn new(len: nat, f: spec_fn(int) -> A) -> Seq<A>
158 decreases len,
159 {
160 if len == 0 {
161 Seq { inner: SeqInner::Nil }
162 } else {
163 Self::new((len - 1) as nat, f).push(f(len - 1))
164 }
165 }
166
167 #[rustc_diagnostic_item = "verus::vstd::seq::Seq::len"]
169 pub closed spec fn len(self) -> nat {
170 self.inner.len()
171 }
172
173 #[rustc_diagnostic_item = "verus::vstd::seq::Seq::index"]
178 pub closed spec fn index(self, i: int) -> A
179 recommends
180 0 <= i < self.len(),
181 {
182 self.inner.index(i)
183 }
184
185 #[verifier::inline]
187 pub open spec fn spec_index(self, i: int) -> A
188 recommends
189 0 <= i < self.len(),
190 {
191 self.index(i)
192 }
193
194 #[rustc_diagnostic_item = "verus::vstd::seq::Seq::push"]
207 pub closed spec fn push(self, a: A) -> Seq<A> {
208 Seq { inner: self.inner.push(a) }
209 }
210
211 #[rustc_diagnostic_item = "verus::vstd::seq::Seq::update"]
224 pub closed spec fn update(self, i: int, a: A) -> Seq<A>
225 recommends
226 0 <= i < self.len(),
227 {
228 Seq { inner: self.inner.update(i, a) }
229 }
230
231 #[rustc_diagnostic_item = "verus::vstd::seq::Seq::subrange"]
245 pub closed spec fn subrange(self, start_inclusive: int, end_exclusive: int) -> Seq<A>
246 recommends
247 0 <= start_inclusive <= end_exclusive <= self.len(),
248 {
249 Seq { inner: self.inner.subrange(start_inclusive, end_exclusive) }
250 }
251
252 #[verifier::inline]
254 pub open spec fn take(self, n: int) -> Seq<A> {
255 self.subrange(0, n)
256 }
257
258 #[verifier::inline]
260 pub open spec fn skip(self, n: int) -> Seq<A> {
261 self.subrange(n, self.len() as int)
262 }
263
264 #[rustc_diagnostic_item = "verus::vstd::seq::Seq::add"]
275 pub closed spec fn add(self, rhs: Seq<A>) -> Seq<A> {
276 Seq { inner: self.inner.add(rhs.inner) }
277 }
278
279 #[verifier::inline]
281 pub open spec fn spec_add(self, rhs: Seq<A>) -> Seq<A> {
282 self.add(rhs)
283 }
284
285 #[rustc_diagnostic_item = "verus::vstd::seq::Seq::last"]
287 pub open spec fn last(self) -> A
288 recommends
289 0 < self.len(),
290 {
291 self[self.len() as int - 1]
292 }
293
294 #[rustc_diagnostic_item = "vstd::seq::Seq::first"]
296 pub open spec fn first(self) -> A
297 recommends
298 0 < self.len(),
299 {
300 self[0]
301 }
302
303 #[verifier(external_body)]
304 pub proof fn tracked_empty() -> (tracked ret: Self)
305 ensures
306 ret == Seq::empty(),
307 {
308 unimplemented!()
309 }
310
311 #[verifier(external_body)]
312 pub proof fn tracked_remove(tracked &mut self, i: int) -> (tracked ret: A)
313 requires
314 0 <= i < old(self).len(),
315 ensures
316 ret == old(self)[i],
317 final(self).len() == old(self).len() - 1,
318 *final(self) == old(self).remove(i),
319 {
320 unimplemented!()
321 }
322
323 #[verifier(external_body)]
324 pub proof fn tracked_insert(tracked &mut self, i: int, tracked v: A)
325 requires
326 0 <= i <= old(self).len(),
327 ensures
328 final(self).len() == old(self).len() + 1,
329 *final(self) == old(self).insert(i, v),
330 {
331 unimplemented!()
332 }
333
334 #[verifier(external_body)]
335 pub proof fn tracked_borrow(tracked &self, i: int) -> (tracked ret: &A)
336 requires
337 0 <= i < self.len(),
338 ensures
339 *ret == self[i],
340 {
341 unimplemented!()
342 }
343
344 pub proof fn tracked_push(tracked &mut self, tracked v: A)
345 ensures
346 *final(self) == old(self).push(v),
347 final(self).len() == old(self).len() + 1,
348 {
349 broadcast use group_seq_axioms;
350
351 assert(self.insert(self.len() as int, v) =~= self.push(v));
352 self.tracked_insert(self.len() as int, v);
353 }
354
355 pub proof fn tracked_pop(tracked &mut self) -> (tracked ret: A)
356 requires
357 old(self).len() > 0,
358 ensures
359 ret == old(self).last(),
360 final(self).len() == old(self).len() - 1,
361 *final(self) == old(self).take(old(self).len() - 1),
362 {
363 broadcast use group_seq_axioms;
364
365 assert(self.remove(self.len() - 1) =~= self.take(self.len() - 1));
366 self.tracked_remove(self.len() - 1)
367 }
368
369 pub proof fn tracked_pop_front(tracked &mut self) -> (tracked ret: A)
370 requires
371 old(self).len() > 0,
372 ensures
373 ret == old(self).first(),
374 final(self).len() == old(self).len() - 1,
375 *final(self) == old(self).drop_first(),
376 {
377 broadcast use group_seq_axioms;
378
379 assert(self.remove(0) =~= self.drop_first());
380 self.tracked_remove(0)
381 }
382}
383
384proof fn lemma_seq_inner_index_decreases<A>(s: SeqInner<A>, i: int)
385 requires
386 0 <= i < s.len(),
387 ensures
388 (decreases_to!(s => s[i])),
389 decreases i,
390{
391 match s {
392 SeqInner::Nil => {
393 assert(s.len() == 0);
394 assert(false);
395 },
396 SeqInner::Cons { head, tail } => {
397 if i == 0 {
398 assert(decreases_to!(s => s[i]));
399 } else {
400 assert(tail[i - 1] == s[i]);
401 lemma_seq_inner_index_decreases(tail@, i - 1);
402 assert(decreases_to!(s => tail@));
403 assert(decreases_to!(tail@ => tail[i-1]));
404 }
405 },
406 }
407}
408
409pub broadcast proof fn axiom_seq_index_decreases<A>(s: Seq<A>, i: int)
410 requires
411 0 <= i < s.len(),
412 ensures
413 #[trigger] (decreases_to!(s => s[i])),
414{
415 lemma_seq_inner_index_decreases(s.inner, i)
416}
417
418pub axiom fn axiom_seq_len_decreases<A>(s1: Seq<A>, s2: Seq<A>)
420 requires
421 s2.len() < s1.len(),
422 forall|i2: int|
423 0 <= i2 < s2.len() && #[trigger] trigger(s2[i2]) ==> exists|i1: int|
424 0 <= i1 < s1.len() && s1[i1] == s2[i2],
425 ensures
426 decreases_to!(s1 => s2),
427;
428
429pub broadcast proof fn axiom_seq_subrange_decreases<A>(s: Seq<A>, i: int, j: int)
430 requires
431 0 <= i <= j <= s.len(),
432 s.subrange(i, j).len() < s.len(),
433 ensures
434 #[trigger] (decreases_to!(s => s.subrange(i, j))),
435{
436 broadcast use {axiom_seq_subrange_len, axiom_seq_subrange_index};
437
438 let s2 = s.subrange(i, j);
439 assert forall|i2: int| 0 <= i2 < s2.len() && #[trigger] trigger(s2[i2]) implies exists|i1: int|
440 0 <= i1 < s.len() && s[i1] == s2[i2] by {
441 assert(s[i + i2] == s2[i2]);
442 }
443 axiom_seq_len_decreases(s, s2);
444}
445
446pub broadcast proof fn axiom_seq_empty<A>()
447 ensures
448 #[trigger] Seq::<A>::empty().len() == 0,
449{
450 let s = Seq::<A>::empty();
451 match s.inner {
452 SeqInner::Nil => {
453 assert(s == Seq { inner: SeqInner::Nil });
454 },
455 SeqInner::Cons { tail, .. } => {
456 let seq_tail = Seq { inner: tail@ };
457 assert(s.len() == 1 + seq_tail.len());
458 assert(s.len() > 0);
459 },
460 }
461}
462
463pub broadcast proof fn axiom_seq_new_len<A>(len: nat, f: spec_fn(int) -> A)
464 ensures
465 #[trigger] Seq::new(len, f).len() == len,
466 decreases len,
467{
468 let s = Seq::new(len, f);
469 if len == 0 {
470 assert(s.len() == 0);
471 } else {
472 broadcast use axiom_seq_push_len;
473
474 let pref = Seq::new((len - 1) as nat, f);
475 axiom_seq_new_len((len - 1) as nat, f);
476 assert(pref.len() == (len - 1) as nat);
477
478 let s2 = pref.push(f(len - 1));
479 assert(s2.len() == pref.len() + 1);
480
481 assert(s == s2);
482 assert(s.len() == len);
483 }
484}
485
486pub broadcast proof fn axiom_seq_new_index<A>(len: nat, f: spec_fn(int) -> A, i: int)
487 requires
488 0 <= i < len,
489 ensures
490 #[trigger] Seq::new(len, f)[i] == f(i),
491 decreases len,
492{
493 broadcast use axiom_seq_new_len;
494
495 let s = Seq::new(len, f);
496 assert(s.len() == len);
497
498 let pref = Seq::new((len - 1) as nat, f);
499 assert(pref.len() == len - 1);
500
501 let a = f(len - 1);
502 assert(s == pref.push(a));
503
504 if i == len - 1 {
505 axiom_seq_push_index_same(pref, a, i);
506 assert(s[i] == a);
507 } else {
508 assert(0 <= i < (len - 1));
509 axiom_seq_new_index((len - 1) as nat, f, i);
510 axiom_seq_push_index_different(pref, a, i);
511 }
512}
513
514proof fn lemma_seq_inner_push_len<A>(s: SeqInner<A>, a: A)
515 ensures
516 s.push(a).len() == s.len() + 1,
517 decreases s.len(),
518{
519 match s {
520 SeqInner::Nil => {},
521 SeqInner::Cons { tail, .. } => {
522 lemma_seq_inner_push_len(tail@, a);
523 },
524 }
525}
526
527pub broadcast proof fn axiom_seq_push_len<A>(s: Seq<A>, a: A)
528 ensures
529 #[trigger] s.push(a).len() == s.len() + 1,
530{
531 lemma_seq_inner_push_len(s.inner, a)
532}
533
534proof fn lemma_seq_inner_push_index_same<A>(s: SeqInner<A>, a: A, i: int)
535 requires
536 i == s.len(),
537 ensures
538 #[trigger] s.push(a)[i] == a,
539 decreases s,
540{
541 match s {
542 SeqInner::Nil => {
543 assert(s.push(a) == SeqInner::Cons { head: a, tail: Ghost(SeqInner::Nil) });
544 assert(s.push(a)[0] == a);
545 },
546 SeqInner::Cons { tail, .. } => {
547 lemma_seq_inner_push_index_same(tail@, a, i - 1);
548 },
549 }
550}
551
552pub broadcast proof fn axiom_seq_push_index_same<A>(s: Seq<A>, a: A, i: int)
553 requires
554 i == s.len(),
555 ensures
556 #[trigger] s.push(a)[i] == a,
557{
558 lemma_seq_inner_push_index_same(s.inner, a, i);
559}
560
561proof fn lemma_seq_inner_index_out_of_bounds<A>(s: SeqInner<A>, i: int)
562 requires
563 !(0 <= i < s.len()),
564 ensures
565 s[i] == arbitrary::<A>(),
566 decreases s,
567{
568 match s {
569 SeqInner::Nil => {},
570 SeqInner::Cons { tail, .. } => {
571 lemma_seq_inner_index_out_of_bounds(tail@, i - 1);
572 },
573 }
574}
575
576proof fn lemma_seq_inner_push_index_different<A>(s: SeqInner<A>, a: A, i: int)
577 requires
578 i < s.len(),
579 ensures
580 #[trigger] s.push(a)[i] == s[i],
581 decreases s,
582{
583 match s {
584 SeqInner::Nil => {
585 lemma_seq_inner_index_out_of_bounds(s.push(a), i);
586 },
587 SeqInner::Cons { tail, .. } => {
588 if i == 0 {
589 } else {
590 lemma_seq_inner_push_index_different(tail@, a, i - 1);
591 }
592 },
593 }
594}
595
596pub broadcast proof fn axiom_seq_push_index_different<A>(s: Seq<A>, a: A, i: int)
597 requires
598 i < s.len(),
599 ensures
600 #[trigger] s.push(a)[i] == s[i],
601{
602 lemma_seq_inner_push_index_different(s.inner, a, i);
603}
604
605pub broadcast proof fn lemma_seq_push_index_different_alt<A>(s: Seq<A>, a: A, i: int)
607 requires
608 i < s.len(),
609 ensures
610 (#[trigger] s.push(a))[i] == #[trigger] s[i],
611{
612 broadcast use axiom_seq_push_index_different;
613
614}
615
616proof fn lemma_seq_inner_update_len<A>(s: SeqInner<A>, i: int, a: A)
617 ensures
618 s.update(i, a).len() == s.len(),
619 decreases i,
620{
621 if !(0 <= i < s.len()) {
622 assert(s.update(i, a) == s);
623 } else {
624 let s_upd = s.update(i, a);
625 match s {
626 SeqInner::Nil => {},
627 SeqInner::Cons { head, tail } => {
628 match s_upd {
629 SeqInner::Nil => {},
630 SeqInner::Cons { head: head_upd, tail: tail_upd } => {
631 if i == 0 {
632 assert(head_upd == a);
633 } else {
634 lemma_seq_inner_update_len(tail@, (i - 1), a);
635 }
636 },
637 }
638 },
639 }
640 }
641}
642
643pub broadcast proof fn axiom_seq_update_len<A>(s: Seq<A>, i: int, a: A)
644 ensures
645 #[trigger] s.update(i, a).len() == s.len(),
646 decreases i,
647{
648 lemma_seq_inner_update_len(s.inner, i, a)
649}
650
651proof fn lemma_seq_inner_update_index_same<A>(s: SeqInner<A>, i: int, a: A)
652 requires
653 0 <= i < s.len(),
654 ensures
655 #[trigger] s.update(i, a)[i] == a,
656 decreases s,
657{
658 match s {
659 SeqInner::Nil => {},
660 SeqInner::Cons { tail, .. } => {
661 if i == 0 {
662 assert(s.update(i, a)[i] == a)
663 } else {
664 lemma_seq_inner_update_index_same(tail@, i - 1, a);
665 }
666 },
667 }
668}
669
670pub broadcast proof fn axiom_seq_update_same<A>(s: Seq<A>, i: int, a: A)
671 requires
672 0 <= i < s.len(),
673 ensures
674 #[trigger] s.update(i, a)[i] == a,
675{
676 lemma_seq_inner_update_index_same(s.inner, i, a);
677}
678
679pub broadcast proof fn lemma_seq_update_same_alt<A>(s: Seq<A>, i: int, a: A)
681 requires
682 0 <= i < s.len(),
683 ensures
684 #![trigger s.update(i, a), s[i]]
685 s.update(i, a)[i] == a,
686{
687 broadcast use axiom_seq_update_same;
688
689}
690
691proof fn lemma_seq_inner_update_index_different<A>(s: SeqInner<A>, i1: int, i2: int, a: A)
692 requires
693 i1 != i2,
694 ensures
695 #[trigger] s.update(i2, a)[i1] == s[i1],
696 decreases s,
697{
698 if !(0 <= i2 < s.len()) {
699 assert(s.update(i2, a) == s);
700 } else {
701 match s {
702 SeqInner::Nil => {},
703 SeqInner::Cons { tail, .. } => {
704 if i2 == 0 {
705 assert(s.update(i2, a)[i1] == s[i1]);
706 } else if i1 == 0 {
707 assert(s.update(i2, a)[i1] == s[i1]);
708 } else {
709 lemma_seq_inner_update_index_different(tail@, i1 - 1, i2 - 1, a);
710 }
711 },
712 }
713 }
714}
715
716pub broadcast proof fn axiom_seq_update_different<A>(s: Seq<A>, i1: int, i2: int, a: A)
717 requires
718 i1 != i2,
719 ensures
720 #[trigger] s.update(i2, a)[i1] == s[i1],
721{
722 lemma_seq_inner_update_index_different(s.inner, i1, i2, a);
723}
724
725pub broadcast proof fn lemma_seq_update_different_alt<A>(s: Seq<A>, i1: int, i2: int, a: A)
727 requires
728 i1 != i2,
729 ensures
730 (#[trigger] s.update(i2, a))[i1] == #[trigger] s[i1],
731{
732 broadcast use axiom_seq_update_different;
733
734}
735
736pub broadcast proof fn axiom_seq_ext_equal<A>(s1: Seq<A>, s2: Seq<A>)
737 ensures
738 #[trigger] (s1 =~= s2) <==> {
739 &&& s1.len() == s2.len()
740 &&& forall|i: int| 0 <= i < s1.len() ==> s1[i] == s2[i]
741 },
742 decreases s1.len(),
743{
744 match s1.inner {
745 SeqInner::Nil => {
746 assert(s1.len() == s2.len() <==> s1 =~= s2);
747 },
748 SeqInner::Cons { head: head1, tail: tail1 } => {
749 let seq_tail1 = Seq { inner: tail1@ };
750
751 match s2.inner {
752 SeqInner::Nil => {
753 assert(s1.len() != s2.len());
754 },
755 SeqInner::Cons { head: head2, tail: tail2 } => {
756 if head1 != head2 {
757 assert(s1[0] != s2[0]);
758 } else {
759 let seq_tail2 = Seq { inner: tail2@ };
760 axiom_seq_ext_equal(seq_tail1, seq_tail2);
761 if seq_tail1 =~= seq_tail2 {
762 assert(s1.len() == seq_tail1.len() + 1 == seq_tail2.len() + 1
763 == s2.len());
764 assert forall|i: int| 0 <= i < s1.len() implies s1[i] == s2[i] by {
765 if i == 0 {
766 assert(s1[0] == s2[0]);
767 } else {
768 assert(s1[i] == s2[i]);
769 }
770 }
771 } else if seq_tail1.len() == seq_tail2.len() {
772 assert(exists|i: int|
773 0 <= i < seq_tail1.len() && seq_tail1[i] != seq_tail2[i]);
774 let i = choose|i: int|
775 0 <= i < seq_tail1.len() && seq_tail1[i] != seq_tail2[i];
776 assert(s1[i + 1] != s2[i + 1]);
777 } else {
778 assert(s1.len() != s2.len());
779 }
780 }
781 },
782 }
783 },
784 }
785}
786
787pub broadcast proof fn axiom_seq_ext_equal_deep<A>(s1: Seq<A>, s2: Seq<A>)
788 ensures
789 #[trigger] (s1 =~~= s2) <==> {
790 &&& s1.len() == s2.len()
791 &&& forall|i: int| 0 <= i < s1.len() ==> s1[i] =~~= s2[i]
792 },
793{
794 match s1.inner {
795 SeqInner::Nil => {
796 assert(s1.len() == s2.len() <==> s1 =~~= s2);
797 },
798 SeqInner::Cons { head: head1, tail: tail1 } => {
799 let seq_tail1 = Seq { inner: tail1@ };
800
801 match s2.inner {
802 SeqInner::Nil => {
803 assert(s1.len() != s2.len());
804 },
805 SeqInner::Cons { head: head2, tail: tail2 } => {
806 if head1 != head2 {
807 assert(s1[0] != s2[0]);
808 } else {
809 let seq_tail2 = Seq { inner: tail2@ };
810 axiom_seq_ext_equal(seq_tail1, seq_tail2);
811 if seq_tail1 =~~= seq_tail2 {
812 assert(s1.len() == seq_tail1.len() + 1 == seq_tail2.len() + 1
813 == s2.len());
814 assert forall|i: int| 0 <= i < s1.len() implies s1[i] == s2[i] by {
815 if i == 0 {
816 assert(s1[0] == s2[0]);
817 } else {
818 assert(s1[i] == s2[i]);
819 }
820 }
821 } else if seq_tail1.len() == seq_tail2.len() {
822 assert(exists|i: int|
823 0 <= i < seq_tail1.len() && seq_tail1[i] != seq_tail2[i]);
824 let i = choose|i: int|
825 0 <= i < seq_tail1.len() && seq_tail1[i] != seq_tail2[i];
826 assert(s1[i + 1] != s2[i + 1]);
827 } else {
828 assert(s1.len() != s2.len());
829 }
830 }
831 },
832 }
833 },
834 }
835}
836
837proof fn lemma_seq_inner_subrange_len<A>(s: SeqInner<A>, j: int, k: int)
838 requires
839 0 <= j <= k <= s.len(),
840 ensures
841 s.subrange(j, k).len() == k - j,
842 decreases j, k,
843{
844 match s {
845 SeqInner::Nil => {},
846 SeqInner::Cons { head, tail } => {
847 if j > 0 {
848 assert(s.subrange(j, k) == tail.subrange(j - 1, k - 1));
849 lemma_seq_inner_subrange_len(tail@, j - 1, k - 1);
850 } else if k > 0 {
851 let new_tail = tail@.subrange(j, k - 1);
852 lemma_seq_inner_subrange_len(tail@, j, k - 1);
853 assert(new_tail.len() == k - j - 1);
854 let sub = SeqInner::Cons { head, tail: Ghost(new_tail) };
855 assert(sub.len() == 1 + new_tail.len());
856 } else {
857 assert(j == k == 0);
858 assert(s.subrange(j, k).len() == 0);
859 }
860 },
861 }
862}
863
864pub broadcast proof fn axiom_seq_subrange_len<A>(s: Seq<A>, j: int, k: int)
865 requires
866 0 <= j <= k <= s.len(),
867 ensures
868 #[trigger] s.subrange(j, k).len() == k - j,
869{
870 lemma_seq_inner_subrange_len(s.inner, j, k)
871}
872
873proof fn lemma_seq_inner_subrange_index_aux<A>(s: SeqInner<A>, k: int, i: int)
874 requires
875 0 <= k <= s.len(),
876 0 <= i < k,
877 ensures
878 s.subrange(0, k)[i] == s[i],
879 decreases s,
880{
881 lemma_seq_inner_subrange_len(s, 0, k);
882 match s {
885 SeqInner::Nil => {
886 },
888 SeqInner::Cons { head, tail } => {
889 if i == 0 {
890 assert(s.subrange(0, k)[0] == head);
892 } else {
893 lemma_seq_inner_subrange_index_aux(tail@, k - 1, i - 1);
894 }
895 },
896 }
897}
898
899proof fn lemma_seq_inner_subrange_index<A>(s: SeqInner<A>, j: int, k: int, i: int)
900 requires
901 0 <= j <= k <= s.len(),
902 0 <= i < k - j,
903 ensures
904 s.subrange(j, k)[i] == s[i + j],
905 decreases s,
906{
907 lemma_seq_inner_subrange_len(s, j, k);
908 if j == 0 {
909 lemma_seq_inner_subrange_index_aux(s, k, i);
910 } else {
911 match s {
912 SeqInner::Nil => {
913 assert(false);
914 },
915 SeqInner::Cons { head, tail } => {
916 lemma_seq_inner_subrange_index(tail@, j - 1, k - 1, i);
917 },
918 }
919 }
920}
921
922pub broadcast proof fn axiom_seq_subrange_index<A>(s: Seq<A>, j: int, k: int, i: int)
923 requires
924 0 <= j <= k <= s.len(),
925 0 <= i < k - j,
926 ensures
927 #[trigger] s.subrange(j, k)[i] == s[i + j],
928{
929 lemma_seq_inner_subrange_index(s.inner, j, k, i);
930}
931
932pub broadcast proof fn lemma_seq_subrange_index_alt<A>(s: Seq<A>, j: int, k: int, i: int)
934 requires
935 0 <= j <= k <= s.len(),
936 0 <= i - j < k - j,
937 ensures
938 (#[trigger] s.subrange(j, k))[i - j] == #[trigger] s[i],
939{
940 broadcast use axiom_seq_subrange_index;
941
942}
943
944pub broadcast proof fn lemma_seq_two_subranges_index<A>(s: Seq<A>, j: int, k1: int, k2: int, i: int)
946 requires
947 0 <= j <= k1 <= s.len(),
948 0 <= j <= k2 <= s.len(),
949 0 <= i < k1 - j,
950 0 <= i < k2 - j,
951 ensures
952 #[trigger] s.subrange(j, k1)[i] == (#[trigger] s.subrange(j, k2))[i],
953{
954 broadcast use axiom_seq_subrange_index;
955
956}
957
958proof fn lemma_seq_inner_add_len<A>(s1: SeqInner<A>, s2: SeqInner<A>)
959 ensures
960 s1.add(s2).len() == s1.len() + s2.len(),
961 decreases s1.add(s2).len(),
962{
963 let sum = s1.add(s2);
964 match s1 {
965 SeqInner::Nil => {
966 assert(sum == s2);
967 },
968 SeqInner::Cons { head, tail } => {
969 let new_tail = tail@.add(s2);
970 lemma_seq_inner_add_len(tail@, s2);
971 assert(new_tail.len() == (s1.len() - 1) + s2.len());
972 assert(sum.len() == 1 + new_tail.len());
973 },
974 }
975}
976
977pub broadcast proof fn axiom_seq_add_len<A>(s1: Seq<A>, s2: Seq<A>)
978 ensures
979 #[trigger] s1.add(s2).len() == s1.len() + s2.len(),
980{
981 lemma_seq_inner_add_len(s1.inner, s2.inner);
982}
983
984proof fn lemma_seq_inner_add_index1<A>(s1: SeqInner<A>, s2: SeqInner<A>, i: int)
985 requires
986 i < s1.len(),
987 ensures
988 s1.add(s2)[i] == s1[i],
989 decreases s1,
990{
991 if i < 0 {
992 lemma_seq_inner_index_out_of_bounds(s1, i);
993 lemma_seq_inner_index_out_of_bounds(s1.add(s2), i);
994 } else {
995 match s1 {
996 SeqInner::Nil => {},
997 SeqInner::Cons { head, tail } => {
998 if i == 0 {
999 assert(s1[i] == s1.add(s2)[i]);
1000 } else {
1001 lemma_seq_inner_add_index1(tail@, s2, i - 1);
1002 }
1003 },
1004 }
1005 }
1006}
1007
1008pub broadcast proof fn axiom_seq_add_index1<A>(s1: Seq<A>, s2: Seq<A>, i: int)
1009 requires
1010 i < s1.len(),
1011 ensures
1012 #[trigger] s1.add(s2)[i] == s1[i],
1013{
1014 lemma_seq_inner_add_index1(s1.inner, s2.inner, i)
1015}
1016
1017proof fn lemma_seq_inner_add_index2<A>(s1: SeqInner<A>, s2: SeqInner<A>, i: int)
1018 requires
1019 s1.len() <= i < s1.len() + s2.len(),
1020 ensures
1021 s1.add(s2)[i] == s2[i - s1.len()],
1022 decreases s1,
1023{
1024 match s1 {
1025 SeqInner::Nil => {
1026 assert(s1.add(s2) == s2);
1027 assert(s1.add(s2)[i] == s2[i - s1.len()]);
1028 },
1029 SeqInner::Cons { head, tail } => {
1030 if i == 0 {
1031 assert(s1.add(s2)[i] == s2[i - s1.len()]);
1032 } else {
1033 lemma_seq_inner_add_index2(tail@, s2, i - 1);
1034 assert(s1.add(s2)[i] == s2[i - s1.len()]);
1035 }
1036 },
1037 }
1038}
1039
1040pub broadcast proof fn axiom_seq_add_index2<A>(s1: Seq<A>, s2: Seq<A>, i: int)
1041 requires
1042 s1.len() <= i < s1.len() + s2.len(),
1043 ensures
1044 #[trigger] s1.add(s2)[i] == s2[i - s1.len()],
1045{
1046 lemma_seq_inner_add_index2(s1.inner, s2.inner, i);
1047}
1048
1049pub broadcast proof fn lemma_seq_add_index1_alt<A>(s1: Seq<A>, s2: Seq<A>, i: int)
1051 requires
1052 0 <= i < s1.len(),
1053 ensures
1054 (#[trigger] s1.add(s2))[i] == #[trigger] s1[i],
1055{
1056 broadcast use axiom_seq_add_index1;
1057
1058}
1059
1060pub broadcast proof fn lemma_seq_add_index2_alt<A>(s1: Seq<A>, s2: Seq<A>, i: int)
1062 requires
1063 0 <= i < s2.len(),
1064 ensures
1065 (#[trigger] s1.add(s2))[i + s1.len()] == #[trigger] s2[i],
1066{
1067 broadcast use axiom_seq_add_index2;
1068
1069}
1070
1071pub broadcast group group_seq_axioms {
1072 axiom_seq_index_decreases,
1073 axiom_seq_subrange_decreases,
1074 axiom_seq_empty,
1075 axiom_seq_new_len,
1076 axiom_seq_new_index,
1077 axiom_seq_push_len,
1078 axiom_seq_push_index_same,
1079 axiom_seq_push_index_different,
1080 axiom_seq_update_len,
1081 axiom_seq_update_same,
1082 axiom_seq_update_different,
1083 axiom_seq_ext_equal,
1084 axiom_seq_ext_equal_deep,
1085 axiom_seq_subrange_len,
1086 axiom_seq_subrange_index,
1087 lemma_seq_two_subranges_index,
1088 axiom_seq_add_len,
1089 axiom_seq_add_index1,
1090 axiom_seq_add_index2,
1091}
1092
1093pub broadcast group group_seq_lemmas_expensive {
1095 lemma_seq_push_index_different_alt,
1096 lemma_seq_update_same_alt,
1097 lemma_seq_update_different_alt,
1098 lemma_seq_subrange_index_alt,
1099 lemma_seq_add_index1_alt,
1100 lemma_seq_add_index2_alt,
1101}
1102
1103#[doc(hidden)]
1105#[macro_export]
1106macro_rules! seq_internal {
1107 [] => {
1108 $crate::vstd::seq::Seq::empty()
1109 };
1110 [$elem:expr] => {
1111 $crate::vstd::seq::Seq::empty()
1112 .push($elem)
1113 };
1114 [$elem:expr,] => {
1115 $crate::vstd::seq::Seq::empty()
1116 .push($elem)
1117 };
1118 [$($elem:expr),* $(,)?] => {
1119 <_ as $crate::vstd::view::View>::view(&[$($elem),*])
1120 };
1121 [$elem:expr; $n:expr] => {
1122 $crate::vstd::seq::Seq::new(
1123 $n,
1124 $crate::vstd::prelude::closure_to_fn_spec(
1125 |_x: _| $elem
1126 ),
1127 )
1128 };
1129}
1130
1131#[macro_export]
1144macro_rules! seq {
1145 [$($tail:tt)*] => {
1146 $crate::vstd::prelude::verus_proof_macro_exprs!($crate::vstd::seq::seq_internal!($($tail)*))
1147 };
1148}
1149
1150#[doc(hidden)]
1151pub use seq_internal;
1152pub use seq;
1153
1154}