vstd/std_specs/
slice.rs

1use super::super::prelude::*;
2use super::core::IndexSetTrustedSpec;
3use super::core::TrustedSpecSealed;
4
5use core::slice::Iter;
6
7use verus as verus_;
8
9verus_! {
10
11impl<T, const N: usize> TrustedSpecSealed for [T; N] {}
12
13impl<T, const N: usize> IndexSetTrustedSpec<usize> for [T; N] {
14    open spec fn spec_index_set_requires(&self, index: usize) -> bool {
15        0 <= index < N
16    }
17
18    open spec fn spec_index_set_ensures(&self, new_container: &Self, index: usize, val: T) -> bool {
19        new_container@ === self@.update(index as int, val)
20    }
21}
22
23impl<T> TrustedSpecSealed for [T] {}
24
25impl<T> IndexSetTrustedSpec<usize> for [T] {
26    open spec fn spec_index_set_requires(&self, index: usize) -> bool {
27        0 <= index < self@.len()
28    }
29
30    open spec fn spec_index_set_ensures(&self, new_container: &Self, index: usize, val: T) -> bool {
31        new_container@ == self@.update(index as int, val)
32    }
33}
34
35pub assume_specification[ core::hint::unreachable_unchecked ]() -> !
36    requires
37        false,
38;
39
40// The `iter` method of a `<T>` returns an iterator of type `Iter<'_, T>`,
41// so we specify that type here.
42#[verifier::external_type_specification]
43#[verifier::external_body]
44#[verifier::accept_recursive_types(T)]
45pub struct ExIter<'a, T: 'a>(Iter<'a, T>);
46
47impl<T> View for Iter<'_, T> {
48    type V = (int, Seq<T>);
49
50    uninterp spec fn view(&self) -> (int, Seq<T>);
51}
52
53impl<T: DeepView> DeepView for Iter<'_, T> {
54    type V = (int, Seq<T::V>);
55
56    open spec fn deep_view(&self) -> Self::V {
57        let (i, v) = self@;
58        (i, Seq::new(v.len(), |i: int| v[i].deep_view()))
59    }
60}
61
62pub assume_specification<'a, T>[ Iter::<'a, T>::next ](elements: &mut Iter<'a, T>) -> (r: Option<
63    &'a T,
64>)
65    ensures
66        ({
67            let (old_index, old_seq) = old(elements)@;
68            match r {
69                None => {
70                    &&& elements@ == old(elements)@
71                    &&& old_index >= old_seq.len()
72                },
73                Some(element) => {
74                    let (new_index, new_seq) = elements@;
75                    &&& 0 <= old_index < old_seq.len()
76                    &&& new_seq == old_seq
77                    &&& new_index == old_index + 1
78                    &&& element == old_seq[old_index]
79                },
80            }
81        }),
82;
83
84pub struct IterGhostIterator<'a, T> {
85    pub pos: int,
86    pub elements: Seq<T>,
87    pub phantom: Option<&'a T>,
88}
89
90impl<'a, T> super::super::pervasive::ForLoopGhostIteratorNew for Iter<'a, T> {
91    type GhostIter = IterGhostIterator<'a, T>;
92
93    open spec fn ghost_iter(&self) -> IterGhostIterator<'a, T> {
94        IterGhostIterator { pos: self@.0, elements: self@.1, phantom: None }
95    }
96}
97
98impl<'a, T: 'a> super::super::pervasive::ForLoopGhostIterator for IterGhostIterator<'a, T> {
99    type ExecIter = Iter<'a, T>;
100
101    type Item = T;
102
103    type Decrease = int;
104
105    open spec fn exec_invariant(&self, exec_iter: &Iter<'a, T>) -> bool {
106        &&& self.pos == exec_iter@.0
107        &&& self.elements == exec_iter@.1
108    }
109
110    open spec fn ghost_invariant(&self, init: Option<&Self>) -> bool {
111        init matches Some(init) ==> {
112            &&& init.pos == 0
113            &&& init.elements == self.elements
114            &&& 0 <= self.pos <= self.elements.len()
115        }
116    }
117
118    open spec fn ghost_ensures(&self) -> bool {
119        self.pos == self.elements.len()
120    }
121
122    open spec fn ghost_decrease(&self) -> Option<int> {
123        Some(self.elements.len() - self.pos)
124    }
125
126    open spec fn ghost_peek_next(&self) -> Option<T> {
127        if 0 <= self.pos < self.elements.len() {
128            Some(self.elements[self.pos])
129        } else {
130            None
131        }
132    }
133
134    open spec fn ghost_advance(&self, _exec_iter: &Iter<'a, T>) -> IterGhostIterator<'a, T> {
135        Self { pos: self.pos + 1, ..*self }
136    }
137}
138
139impl<'a, T> View for IterGhostIterator<'a, T> {
140    type V = Seq<T>;
141
142    open spec fn view(&self) -> Seq<T> {
143        self.elements.take(self.pos)
144    }
145}
146
147// To allow reasoning about the ghost iterator when the executable
148// function `iter()` is invoked in a `for` loop header (e.g., in
149// `for x in it: s.iter() { ... }`), we need to specify the behavior of
150// the iterator in spec mode. To do that, we add
151// `#[verifier::when_used_as_spec(spec_slice_iter)` to the specification for
152// the executable `into_iter` method and define that spec function here.
153pub uninterp spec fn spec_slice_iter<'a, T>(s: &'a [T]) -> (iter: Iter<'a, T>);
154
155pub broadcast proof fn axiom_spec_slice_iter<'a, T>(s: &'a [T])
156    ensures
157        (#[trigger] spec_slice_iter(s))@ == (0int, s@),
158{
159    admit();
160}
161
162#[verifier::when_used_as_spec(spec_slice_iter)]
163pub assume_specification<'a, T>[ <[T]>::iter ](s: &'a [T]) -> (iter: Iter<'a, T>)
164    ensures
165        ({
166            let (index, seq) = iter@;
167            &&& index == 0
168            &&& seq == s@
169        }),
170;
171
172pub assume_specification<T> [ <[T]>::first ](slice: &[T]) -> (res: Option<&T>)
173    ensures
174        slice.len() == 0 ==> res.is_none(),
175        slice.len() != 0 ==> res.is_some() && res.unwrap() == slice[0]
176;
177
178pub assume_specification<T> [ <[T]>::last ](slice: &[T]) -> (res: Option<&T>)
179    ensures
180        slice.len() == 0 ==> res.is_none(),
181        slice.len() != 0 ==> res.is_some() && res.unwrap() == slice@.last()
182;
183
184#[doc(hidden)]
185#[verifier::ignore_outside_new_mut_ref_experiment]
186pub assume_specification<T> [ <[T]>::first_mut ](slice: &mut [T]) -> (res: Option<&mut T>)
187    ensures
188        slice.len() == 0 ==> res.is_none() && fin(slice)@ === seq![],
189        slice.len() != 0 ==> res.is_some() && *res.unwrap() == slice[0]
190            && fin(slice)@ === slice@.update(0, *fin(res.unwrap()))
191;
192
193#[doc(hidden)]
194#[verifier::ignore_outside_new_mut_ref_experiment]
195pub assume_specification<T> [ <[T]>::last_mut ](slice: &mut [T]) -> (res: Option<&mut T>)
196    ensures
197        slice.len() == 0 ==> res.is_none() && fin(slice)@ === seq![],
198        slice.len() != 0 ==> res.is_some() && *res.unwrap() == slice@.last()
199            && fin(slice)@ === slice@.update(slice.len() - 1, *fin(res.unwrap()))
200;
201
202pub assume_specification<T> [ <[T]>::split_at ](slice: &[T], mid: usize) -> (ret: (&[T], &[T]))
203    requires
204        0 <= mid <= slice.len(),
205    ensures
206        ret.0@ == slice@.subrange(0, mid as int),
207        ret.1@ == slice@.subrange(mid as int, slice@.len() as int),
208;
209
210#[doc(hidden)]
211#[verifier::ignore_outside_new_mut_ref_experiment]
212pub assume_specification<T> [ <[T]>::split_at_mut ](slice: &mut [T], mid: usize) -> (ret: (&mut [T], &mut [T]))
213    requires
214        0 <= mid <= slice.len(),
215    ensures
216        ret.0@ == slice@.subrange(0, mid as int),
217        ret.1@ == slice@.subrange(mid as int, slice@.len() as int),
218        fin(slice)@ == fin(ret.0)@ + fin(ret.1)@,
219;
220
221pub broadcast group group_slice_axioms {
222    axiom_spec_slice_iter,
223}
224
225} // verus!