vstd/std_specs/
range.rs
1use super::super::prelude::*;
2use super::super::view::View;
3use core::ops::Range;
4
5verus! {
6
7#[verifier::external_type_specification]
8#[verifier::reject_recursive_types_in_ground_variants(Idx)]
9pub struct ExRange<Idx>(Range<Idx>);
10
11pub trait StepSpec where Self: Sized {
12 spec fn spec_is_lt(self, other: Self) -> bool;
14
15 spec fn spec_steps_between(self, end: Self) -> Option<usize>;
16
17 spec fn spec_steps_between_int(self, end: Self) -> int;
18
19 spec fn spec_forward_checked(self, count: usize) -> Option<Self>;
20
21 spec fn spec_forward_checked_int(self, count: int) -> Option<Self>;
22
23 spec fn spec_backward_checked(self, count: usize) -> Option<Self>;
24
25 spec fn spec_backward_checked_int(self, count: int) -> Option<Self>;
26}
27
28pub uninterp spec fn spec_range_next<A>(a: Range<A>) -> (Range<A>, Option<A>);
29
30pub assume_specification<A: core::iter::Step>[ Range::<A>::next ](range: &mut Range<A>) -> (r:
31 Option<A>)
32 ensures
33 (*range, r) == spec_range_next(*old(range)),
34;
35
36pub struct RangeGhostIterator<A> {
37 pub start: A,
38 pub cur: A,
39 pub end: A,
40}
41
42impl<A: StepSpec> super::super::pervasive::ForLoopGhostIteratorNew for Range<A> {
43 type GhostIter = RangeGhostIterator<A>;
44
45 open spec fn ghost_iter(&self) -> RangeGhostIterator<A> {
46 RangeGhostIterator { start: self.start, cur: self.start, end: self.end }
47 }
48}
49
50impl<
51 A: StepSpec + core::iter::Step,
52> super::super::pervasive::ForLoopGhostIterator for RangeGhostIterator<A> {
53 type ExecIter = Range<A>;
54
55 type Item = A;
56
57 type Decrease = int;
58
59 open spec fn exec_invariant(&self, exec_iter: &Range<A>) -> bool {
60 &&& self.cur == exec_iter.start
61 &&& self.end == exec_iter.end
62 }
63
64 open spec fn ghost_invariant(&self, init: Option<&Self>) -> bool {
65 &&& self.start.spec_is_lt(self.cur) || self.start == self.cur
66 &&& self.cur.spec_is_lt(self.end) || self.cur
67 == self.end
68 &&& if let Some(init) = init {
70 &&& init.start == init.cur
71 &&& init.start == self.start
72 &&& init.end == self.end
73 } else {
74 true
75 }
76 }
77
78 open spec fn ghost_ensures(&self) -> bool {
79 !self.cur.spec_is_lt(self.end)
80 }
81
82 open spec fn ghost_decrease(&self) -> Option<int> {
83 Some(self.cur.spec_steps_between_int(self.end))
84 }
85
86 open spec fn ghost_peek_next(&self) -> Option<A> {
87 Some(self.cur)
88 }
89
90 open spec fn ghost_advance(&self, _exec_iter: &Range<A>) -> RangeGhostIterator<A> {
91 RangeGhostIterator { cur: self.cur.spec_forward_checked(1).unwrap(), ..*self }
92 }
93}
94
95impl<A: StepSpec + core::iter::Step> View for RangeGhostIterator<A> {
96 type V = Seq<A>;
97
98 open spec fn view(&self) -> Seq<A> {
100 Seq::new(
101 self.start.spec_steps_between_int(self.cur) as nat,
102 |i: int| self.start.spec_forward_checked_int(i).unwrap(),
103 )
104 }
105}
106
107} macro_rules! step_specs {
109 ($t: ty, $axiom: ident) => {
110 verus! {
111 impl StepSpec for $t {
112 open spec fn spec_is_lt(self, other: Self) -> bool {
113 self < other
114 }
115 open spec fn spec_steps_between(self, end: Self) -> Option<usize> {
116 let n = end - self;
117 if usize::MIN <= n <= usize::MAX {
118 Some(n as usize)
119 } else {
120 None
121 }
122 }
123 open spec fn spec_steps_between_int(self, end: Self) -> int {
124 end - self
125 }
126 open spec fn spec_forward_checked(self, count: usize) -> Option<Self> {
127 self.spec_forward_checked_int(count as int)
128 }
129 open spec fn spec_forward_checked_int(self, count: int) -> Option<Self> {
130 if self + count <= $t::MAX {
131 Some((self + count) as $t)
132 } else {
133 None
134 }
135 }
136 open spec fn spec_backward_checked(self, count: usize) -> Option<Self> {
137 self.spec_backward_checked_int(count as int)
138 }
139 open spec fn spec_backward_checked_int(self, count: int) -> Option<Self> {
140 if self - count >= $t::MIN {
141 Some((self - count) as $t)
142 } else {
143 None
144 }
145 }
146 }
147 pub broadcast proof fn $axiom(range: Range<$t>)
150 ensures
151 range.start.spec_is_lt(range.end) ==>
152 (if let Some(n) = range.start.spec_forward_checked(1) {
154 spec_range_next(range) == (Range { start: n, ..range }, Some(range.start))
155 } else {
156 true
157 }),
158 !range.start.spec_is_lt(range.end) ==>
159 #[trigger] spec_range_next(range) == (range, None::<$t>),
160 {
161 admit();
162 }
163 } };
165}
166
167step_specs!(u8, axiom_spec_range_next_u8);
168step_specs!(u16, axiom_spec_range_next_u16);
169step_specs!(u32, axiom_spec_range_next_u32);
170step_specs!(u64, axiom_spec_range_next_u64);
171step_specs!(u128, axiom_spec_range_next_u128);
172step_specs!(usize, axiom_spec_range_next_usize);
173step_specs!(i8, axiom_spec_range_next_i8);
174step_specs!(i16, axiom_spec_range_next_i16);
175step_specs!(i32, axiom_spec_range_next_i32);
176step_specs!(i64, axiom_spec_range_next_i64);
177step_specs!(i128, axiom_spec_range_next_i128);
178step_specs!(isize, axiom_spec_range_next_isize);
179
180verus! {
181
182pub broadcast group group_range_axioms {
183 axiom_spec_range_next_u8,
184 axiom_spec_range_next_u16,
185 axiom_spec_range_next_u32,
186 axiom_spec_range_next_u64,
187 axiom_spec_range_next_u128,
188 axiom_spec_range_next_usize,
189 axiom_spec_range_next_i8,
190 axiom_spec_range_next_i16,
191 axiom_spec_range_next_i32,
192 axiom_spec_range_next_i64,
193 axiom_spec_range_next_i128,
194 axiom_spec_range_next_isize,
195}
196
197}