1use super::super::prelude::*;
2use super::super::slice::SliceIndexSpec;
3use super::core::{IndexSetTrustedSpec, IndexSpec, TrustedSpecSealed};
4use super::iter::IteratorSpec;
5
6use core::ops::{Index, Range};
7use core::slice::{Iter, SliceIndex};
8
9use verus as verus_;
10
11verus_! {
12
13impl<T, const N: usize> TrustedSpecSealed for [T; N] {}
14
15impl<T, const N: usize> IndexSetTrustedSpec<usize> for [T; N] {
16 open spec fn spec_index_set_requires(&self, index: usize) -> bool {
17 0 <= index < N
18 }
19
20 open spec fn spec_index_set_ensures(&self, new_container: &Self, index: usize, val: T) -> bool {
21 new_container@ == self@.update(index as int, val)
22 }
23}
24
25impl<T> TrustedSpecSealed for [T] {}
26
27impl<T> IndexSetTrustedSpec<usize> for [T] {
28 open spec fn spec_index_set_requires(&self, index: usize) -> bool {
29 0 <= index < self@.len()
30 }
31
32 open spec fn spec_index_set_ensures(&self, new_container: &Self, index: usize, val: T) -> bool {
33 new_container@ == self@.update(index as int, val)
34 }
35}
36
37impl<T> super::super::slice::SliceIndexSpecImpl<[T]> for usize {
38 open spec fn index_req(&self, slice: &[T]) -> bool {
39 *self < slice@.len()
40 }
41}
42
43pub assume_specification<T>[ <usize as SliceIndex<[T]>>::index ](i: usize, slice: &[T]) -> &T
44 returns
45 slice@[i as int],
46;
47
48impl<T> super::super::slice::SliceIndexSpecImpl<[T]> for Range<usize> {
49 open spec fn index_req(&self, slice: &[T]) -> bool {
50 &&& self.start <= self.end
51 &&& self.end <= slice@.len()
52 }
53}
54
55pub assume_specification<T>[ <Range<usize> as SliceIndex<[T]>>::index ](i: Range<usize>, slice: &[T]) -> (r: &[T])
56 ensures
57 r@ == slice@.subrange(i.start as int, i.end as int),
58;
59
60impl<T, I: SliceIndex<[T]>> super::core::IndexSpecImpl<I> for [T] {
61 open spec fn index_req(&self, index: &I) -> bool {
62 index.index_req(self)
63 }
64}
65
66impl<T, I, const N: usize> super::core::IndexSpecImpl<I> for [T; N]
67 where [T]: Index<I>
68{
69 open spec fn index_req(&self, index: &I) -> bool {
70 <[T] as IndexSpec<I>>::index_req(self, index)
71 }
72}
73
74pub assume_specification<T, I: SliceIndex<[T]>> [<[T] as Index<I>>::index] (
75 slice: &[T],
76 index: I,
77) -> (output: &<I as core::slice::SliceIndex<[T]>>::Output)
78 ensures
79 call_ensures(<I as SliceIndex<[T]>>::index, (index, slice), output),
80;
81
82pub assume_specification<T, I, const N: usize> [<[T; N] as Index<I>>::index] (
83 array: &[T; N],
84 index: I,
85) -> (output: &<[T; N] as core::ops::Index<I>>::Output)
86 where [T]: Index<I>,
87 ensures
88 call_ensures(<[T] as Index<I>>::index, (array, index), output),
89;
90
91pub assume_specification[ core::hint::unreachable_unchecked ]() -> !
92 requires
93 false,
94;
95
96#[verifier::external_type_specification]
99#[verifier::external_body]
100#[verifier::accept_recursive_types(T)]
101pub struct ExIter<'a, T: 'a>(Iter<'a, T>);
102
103pub uninterp spec fn into_iter_elts<'a, T: 'a>(i: Iter<'a, T>) -> Seq<T>;
106
107impl <'a, T: 'a> super::iter::IteratorSpecImpl for Iter<'a, T> {
108 open spec fn obeys_prophetic_iter_laws(&self) -> bool {
109 true
110 }
111
112 uninterp spec fn remaining(&self) -> Seq<Self::Item>;
113 uninterp spec fn will_return_none(&self) -> bool;
114
115 #[verifier::prophetic]
116 open spec fn initial_value_relation(&self, init: &Self) -> bool {
117 &&& IteratorSpec::remaining(init) == IteratorSpec::remaining(self)
118 &&& into_iter_elts(*self) == IteratorSpec::remaining(self).unref()
119 }
120
121 uninterp spec fn decrease(&self) -> Option<nat>;
122
123 open spec fn peek(&self, index: int) -> Option<Self::Item> {
124 if 0 <= index < into_iter_elts(*self).len() {
125 Some(&into_iter_elts(*self)[index])
126 } else {
127 None
128 }
129 }
130}
131
132
133pub uninterp spec fn spec_slice_iter<'a, T>(s: &'a [T]) -> (iter: Iter<'a, T>);
140
141pub broadcast proof fn axiom_spec_slice_iter<'a, T>(s: &'a [T])
142 ensures
143 #[trigger] spec_slice_iter(s).remaining() == s@.as_ref(),
144{
145 admit();
146}
147
148#[verifier::when_used_as_spec(spec_slice_iter)]
149pub assume_specification<'a, T>[ <[T]>::iter ](s: &'a [T]) -> (iter: Iter<'a, T>)
150 ensures
151 iter == spec_slice_iter(s),
152 IteratorSpec::decrease(&iter) is Some,
153 IteratorSpec::initial_value_relation(&iter, &iter),
154;
155
156#[verifier::when_used_as_spec(spec_slice_iter)]
157pub assume_specification<'a, T> [<&'a [T] as core::iter::IntoIterator>::into_iter] (s: &'a [T]) ->
158 (iter: Iter<'a, T>)
159 ensures
160 iter == spec_slice_iter(s),
161 IteratorSpec::decrease(&iter) is Some,
162 IteratorSpec::initial_value_relation(&iter, &iter),
163;
164
165pub assume_specification<T> [ <[T]>::first ](slice: &[T]) -> (res: Option<&T>)
166 ensures
167 slice.len() == 0 ==> res.is_none(),
168 slice.len() != 0 ==> res.is_some() && res.unwrap() == slice[0]
169;
170
171pub assume_specification<T> [ <[T]>::last ](slice: &[T]) -> (res: Option<&T>)
172 ensures
173 slice.len() == 0 ==> res.is_none(),
174 slice.len() != 0 ==> res.is_some() && res.unwrap() == slice@.last()
175;
176
177#[doc(hidden)]
178pub assume_specification<T> [ <[T]>::first_mut ](slice: &mut [T]) -> (res: Option<&mut T>)
179 ensures
180 old(slice).len() == 0 ==> res.is_none() && final(slice)@ == seq![],
181 old(slice).len() != 0 ==> res.is_some() && *res.unwrap() == old(slice)[0]
182 && final(slice)@ == old(slice)@.update(0, *final(res.unwrap()))
183;
184
185#[doc(hidden)]
186pub assume_specification<T> [ <[T]>::last_mut ](slice: &mut [T]) -> (res: Option<&mut T>)
187 ensures
188 old(slice).len() == 0 ==> res.is_none() && final(slice)@ == seq![],
189 old(slice).len() != 0 ==> res.is_some() && *res.unwrap() == old(slice)@.last()
190 && final(slice)@ == old(slice)@.update(old(slice).len() - 1, *final(res.unwrap()))
191;
192
193pub assume_specification<T> [ <[T]>::split_at ](slice: &[T], mid: usize) -> (ret: (&[T], &[T]))
194 requires
195 0 <= mid <= slice.len(),
196 ensures
197 ret.0@ == slice@.subrange(0, mid as int),
198 ret.1@ == slice@.subrange(mid as int, slice@.len() as int),
199;
200
201#[doc(hidden)]
202pub assume_specification<T> [ <[T]>::split_at_mut ](slice: &mut [T], mid: usize) -> (ret: (&mut [T], &mut [T]))
203 requires
204 0 <= mid <= slice.len(),
205 ensures
206 ret.0@ == old(slice)@.subrange(0, mid as int),
207 ret.1@ == old(slice)@.subrange(mid as int, old(slice)@.len() as int),
208 final(slice)@ == final(ret.0)@ + final(ret.1)@,
209;
210
211pub broadcast group group_slice_axioms {
212 axiom_spec_slice_iter,
213}
214
215}