use super::super::prelude::*;
use super::super::slice::SliceIndexSpec;
use super::core::{IndexSetTrustedSpec, IndexSpec, TrustedSpecSealed};
use core::ops::{Index, Range};
use core::slice::{Iter, SliceIndex};
use verus as verus_;
verus_! {
impl<T, const N: usize> TrustedSpecSealed for [T; N] {}
impl<T, const N: usize> IndexSetTrustedSpec<usize> for [T; N] {
open spec fn spec_index_set_requires(&self, index: usize) -> bool {
0 <= index < N
}
open spec fn spec_index_set_ensures(&self, new_container: &Self, index: usize, val: T) -> bool {
new_container@ === self@.update(index as int, val)
}
}
impl<T> TrustedSpecSealed for [T] {}
impl<T> IndexSetTrustedSpec<usize> for [T] {
open spec fn spec_index_set_requires(&self, index: usize) -> bool {
0 <= index < self@.len()
}
open spec fn spec_index_set_ensures(&self, new_container: &Self, index: usize, val: T) -> bool {
new_container@ == self@.update(index as int, val)
}
}
impl<T> super::super::slice::SliceIndexSpecImpl<[T]> for usize {
open spec fn index_req(&self, slice: &[T]) -> bool {
*self < slice@.len()
}
}
pub assume_specification<T>[ <usize as SliceIndex<[T]>>::index ](i: usize, slice: &[T]) -> &T
returns
slice@[i as int],
;
impl<T> super::super::slice::SliceIndexSpecImpl<[T]> for Range<usize> {
open spec fn index_req(&self, slice: &[T]) -> bool {
&&& self.start <= self.end
&&& self.end <= slice@.len()
}
}
pub assume_specification<T>[ <Range<usize> as SliceIndex<[T]>>::index ](i: Range<usize>, slice: &[T]) -> (r: &[T])
ensures
r@ == slice@.subrange(i.start as int, i.end as int),
;
impl<T, I: SliceIndex<[T]>> super::core::IndexSpecImpl<I> for [T] {
open spec fn index_req(&self, index: &I) -> bool {
index.index_req(self)
}
}
impl<T, I, const N: usize> super::core::IndexSpecImpl<I> for [T; N]
where [T]: Index<I>
{
open spec fn index_req(&self, index: &I) -> bool {
<[T] as IndexSpec<I>>::index_req(self, index)
}
}
pub assume_specification<T, I: SliceIndex<[T]>> [<[T] as Index<I>>::index] (
slice: &[T],
index: I,
) -> (output: &<I as core::slice::SliceIndex<[T]>>::Output)
ensures
call_ensures(<I as SliceIndex<[T]>>::index, (index, slice), output),
;
pub assume_specification<T, I, const N: usize> [<[T; N] as Index<I>>::index] (
array: &[T; N],
index: I,
) -> (output: &<[T; N] as core::ops::Index<I>>::Output)
where [T]: Index<I>,
ensures
call_ensures(<[T] as Index<I>>::index, (array, index), output),
;
pub assume_specification[ core::hint::unreachable_unchecked ]() -> !
requires
false,
;
#[verifier::external_type_specification]
#[verifier::external_body]
#[verifier::accept_recursive_types(T)]
pub struct ExIter<'a, T: 'a>(Iter<'a, T>);
impl<T> View for Iter<'_, T> {
type V = (int, Seq<T>);
uninterp spec fn view(&self) -> (int, Seq<T>);
}
impl<T: DeepView> DeepView for Iter<'_, T> {
type V = (int, Seq<T::V>);
open spec fn deep_view(&self) -> Self::V {
let (i, v) = self@;
(i, Seq::new(v.len(), |i: int| v[i].deep_view()))
}
}
pub assume_specification<'a, T>[ Iter::<'a, T>::next ](elements: &mut Iter<'a, T>) -> (r: Option<
&'a T,
>)
ensures
({
let (old_index, old_seq) = old(elements)@;
match r {
None => {
&&& elements@ == old(elements)@
&&& old_index >= old_seq.len()
},
Some(element) => {
let (new_index, new_seq) = elements@;
&&& 0 <= old_index < old_seq.len()
&&& new_seq == old_seq
&&& new_index == old_index + 1
&&& element == old_seq[old_index]
},
}
}),
;
pub struct IterGhostIterator<'a, T> {
pub pos: int,
pub elements: Seq<T>,
pub phantom: Option<&'a T>,
}
impl<'a, T> super::super::pervasive::ForLoopGhostIteratorNew for Iter<'a, T> {
type GhostIter = IterGhostIterator<'a, T>;
open spec fn ghost_iter(&self) -> IterGhostIterator<'a, T> {
IterGhostIterator { pos: self@.0, elements: self@.1, phantom: None }
}
}
impl<'a, T: 'a> super::super::pervasive::ForLoopGhostIterator for IterGhostIterator<'a, T> {
type ExecIter = Iter<'a, T>;
type Item = T;
type Decrease = int;
open spec fn exec_invariant(&self, exec_iter: &Iter<'a, T>) -> bool {
&&& self.pos == exec_iter@.0
&&& self.elements == exec_iter@.1
}
open spec fn ghost_invariant(&self, init: Option<&Self>) -> bool {
init matches Some(init) ==> {
&&& init.pos == 0
&&& init.elements == self.elements
&&& 0 <= self.pos <= self.elements.len()
}
}
open spec fn ghost_ensures(&self) -> bool {
self.pos == self.elements.len()
}
open spec fn ghost_decrease(&self) -> Option<int> {
Some(self.elements.len() - self.pos)
}
open spec fn ghost_peek_next(&self) -> Option<T> {
if 0 <= self.pos < self.elements.len() {
Some(self.elements[self.pos])
} else {
None
}
}
open spec fn ghost_advance(&self, _exec_iter: &Iter<'a, T>) -> IterGhostIterator<'a, T> {
Self { pos: self.pos + 1, ..*self }
}
}
impl<'a, T> View for IterGhostIterator<'a, T> {
type V = Seq<T>;
open spec fn view(&self) -> Seq<T> {
self.elements.take(self.pos)
}
}
pub uninterp spec fn spec_slice_iter<'a, T>(s: &'a [T]) -> (iter: Iter<'a, T>);
pub broadcast proof fn axiom_spec_slice_iter<'a, T>(s: &'a [T])
ensures
(#[trigger] spec_slice_iter(s))@ == (0int, s@),
{
admit();
}
#[verifier::when_used_as_spec(spec_slice_iter)]
pub assume_specification<'a, T>[ <[T]>::iter ](s: &'a [T]) -> (iter: Iter<'a, T>)
ensures
({
let (index, seq) = iter@;
&&& index == 0
&&& seq == s@
}),
;
pub assume_specification<T> [ <[T]>::first ](slice: &[T]) -> (res: Option<&T>)
ensures
slice.len() == 0 ==> res.is_none(),
slice.len() != 0 ==> res.is_some() && res.unwrap() == slice[0]
;
pub assume_specification<T> [ <[T]>::last ](slice: &[T]) -> (res: Option<&T>)
ensures
slice.len() == 0 ==> res.is_none(),
slice.len() != 0 ==> res.is_some() && res.unwrap() == slice@.last()
;
#[doc(hidden)]
#[verifier::ignore_outside_new_mut_ref_experiment]
pub assume_specification<T> [ <[T]>::first_mut ](slice: &mut [T]) -> (res: Option<&mut T>)
ensures
old(slice).len() == 0 ==> res.is_none() && final(slice)@ === seq![],
old(slice).len() != 0 ==> res.is_some() && *res.unwrap() == old(slice)[0]
&& final(slice)@ === old(slice)@.update(0, *final(res.unwrap()))
;
#[doc(hidden)]
#[verifier::ignore_outside_new_mut_ref_experiment]
pub assume_specification<T> [ <[T]>::last_mut ](slice: &mut [T]) -> (res: Option<&mut T>)
ensures
old(slice).len() == 0 ==> res.is_none() && final(slice)@ === seq![],
old(slice).len() != 0 ==> res.is_some() && *res.unwrap() == old(slice)@.last()
&& final(slice)@ === old(slice)@.update(old(slice).len() - 1, *final(res.unwrap()))
;
pub assume_specification<T> [ <[T]>::split_at ](slice: &[T], mid: usize) -> (ret: (&[T], &[T]))
requires
0 <= mid <= slice.len(),
ensures
ret.0@ == slice@.subrange(0, mid as int),
ret.1@ == slice@.subrange(mid as int, slice@.len() as int),
;
#[doc(hidden)]
#[verifier::ignore_outside_new_mut_ref_experiment]
pub assume_specification<T> [ <[T]>::split_at_mut ](slice: &mut [T], mid: usize) -> (ret: (&mut [T], &mut [T]))
requires
0 <= mid <= slice.len(),
ensures
ret.0@ == old(slice)@.subrange(0, mid as int),
ret.1@ == old(slice)@.subrange(mid as int, old(slice)@.len() as int),
final(slice)@ == final(ret.0)@ + final(ret.1)@,
;
pub broadcast group group_slice_axioms {
axiom_spec_slice_iter,
}
}