diff --git a/source/vstd/std_specs/vec.rs b/source/vstd/std_specs/vec.rs index fbe8cea935..384d5ac990 100644 --- a/source/vstd/std_specs/vec.rs +++ b/source/vstd/std_specs/vec.rs @@ -5,7 +5,7 @@ use verus_builtin::*; use super::super::slice::SliceIndexSpec; use super::core::IndexSpec; use alloc::collections::TryReserveError; -use alloc::vec::{IntoIter, Vec}; +use alloc::vec::{Drain, IntoIter, Vec}; use core::alloc::Allocator; use core::clone::Clone; use core::marker::PhantomData; @@ -23,6 +23,16 @@ verus_! { #[verifier::reject_recursive_types(A)] pub struct ExVec(Vec); +#[verifier::external_type_specification] +#[verifier::external_body] +#[verifier::reject_recursive_types(T)] +#[verifier::reject_recursive_types(A)] +pub struct ExDrain<'a, T, A>(Drain<'a, T, A>) +where + T: 'a, + A: Allocator, +; + pub trait VecAdditionalSpecFns: View> { spec fn spec_index(&self, i: int) -> T recommends @@ -485,4 +495,119 @@ pub axiom fn tracked_borrow_mut_slice(tracked vec: &mut Vec[ Drain::<'a, T, A>::as_slice ]( + drain: &'b Drain<'a, T, A>, +) -> (ret: &'b [T]) + ensures + as super::iter::IteratorSpec>::obeys_prophetic_iter_laws(drain), + ret@ == as super::iter::IteratorSpec>::remaining(drain), +; + +pub assume_specification[ IntoIter::::as_mut_slice ]( + iter: &mut IntoIter, +) -> (ret: &mut [T]) + ensures + ret@ == into_iter_elts(*old(iter)), + ret@ == as super::iter::IteratorSpec>::remaining(old(iter)), + into_iter_elts(*final(iter)) == final(ret)@, + as super::iter::IteratorSpec>::remaining(final(iter)) == final(ret)@, + final(ret)@.len() == ret@.len(), +; + +pub assume_specification[ IntoIter::::as_slice ]( + iter: &IntoIter, +) -> (ret: &[T]) + ensures + ret@ == into_iter_elts(*iter), + ret@ == as super::iter::IteratorSpec>::remaining(iter), +; + +pub assume_specification[ Vec::::as_mut_ptr ]( + vec: &mut Vec, +) -> (ptr: *mut T) + ensures + ptr@.addr != 0, + ptr@.addr as nat % super::super::layout::align_of::() == 0, + final(vec)@ == old(vec)@, +; + +pub assume_specification[ Vec::::as_ptr ]( + vec: &Vec, +) -> (ptr: *const T) + ensures + ptr@.addr != 0, + ptr@.addr as nat % super::super::layout::align_of::() == 0, +; + +pub assume_specification[ Vec::::into_boxed_slice ]( + vec: Vec, +) -> (ret: alloc::boxed::Box<[T], A>) + ensures + (*ret)@ == vec@, +; + +pub assume_specification[ + Vec::<[T; N], A>::into_flattened +]( + vec: Vec<[T; N], A>, +) -> (ret: Vec) + requires + super::super::layout::size_of::() != 0 || vec@.len() * N <= usize::MAX, + ensures + ret@.len() == vec@.len() * N, + forall|i: int, j: int| #![trigger ret@[i * N as int + j]] #![trigger vec@[i]@[j]] + 0 <= i < vec@.len() && 0 <= j < N ==> + ret@[i * N as int + j] == vec@[i]@[j], +; + +pub assume_specification<'a, T, A: Allocator + 'a>[ Vec::::leak ]( + vec: Vec, +) -> (ret: &'a mut [T]) + ensures + ret@ == vec@, + final(ret)@.len() == vec@.len(), +; + +pub assume_specification[ Vec::::insert_mut ]( + vec: &mut Vec, + index: usize, + element: T, +) -> (ret: &mut T) + requires + index <= old(vec)@.len(), + ensures + old(vec)@.len() < usize::MAX, + *ret == element, +; + +pub assume_specification bool>[ + Vec::::pop_if +]( + vec: &mut Vec, + predicate: P, +) -> (ret: Option) + ensures + old(vec)@.len() == 0 ==> ret == None:: && final(vec)@ == old(vec)@, + ret.is_none() ==> final(vec)@.len() == old(vec)@.len(), + ret.is_some() ==> final(vec)@.len() + 1 == old(vec)@.len(), + old(vec)@.len() > 0 ==> exists|last: &mut T| #![auto] { + &&& mut_ref_current(last) == old(vec)@.last() + &&& (call_requires(predicate, (last,)) ==> + call_ensures(predicate, (last,), ret.is_some())) + &&& match ret { + Some(value) => value == *final(last), + None => final(vec)@.last() == *final(last), + } + }, +; + +pub assume_specification[ Vec::::push_mut ]( + vec: &mut Vec, + value: T, +) -> (ret: &mut T) + ensures + old(vec)@.len() < usize::MAX, + *ret == value, +; + } // verus!