1use super::super::prelude::*;
2use super::super::view::View;
3use super::cmp::{PartialOrdIs, PartialOrdSpec};
4use super::iter::{IteratorSpec, StepSpec, StepSpecImpl};
5use core::ops::{
6 Bound, Range, RangeBounds, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
7};
8
9verus! {
10
11#[verifier::external_type_specification]
12#[verifier::reject_recursive_types_in_ground_variants(Idx)]
13pub struct ExRange<Idx>(Range<Idx>);
14
15#[verifier::external_type_specification]
16#[verifier::external_body]
17#[verifier::reject_recursive_types_in_ground_variants(Idx)]
18pub struct ExRangeInclusive<Idx>(RangeInclusive<Idx>);
19
20pub struct RangeInclusiveView<Idx> {
21 pub start: Idx,
22 pub end: Idx,
23 pub exhausted: bool,
24}
25
26pub trait ContainsSpec<Idx, U> where Idx: PartialOrd<U>, U: ?Sized + PartialOrd<Idx> {
27 spec fn obeys_contains() -> bool;
28
29 spec fn contains_spec(&self, i: &U) -> bool;
30}
31
32impl<Idx, U> ContainsSpec<Idx, U> for RangeInclusive<Idx> where
33 Idx: PartialOrd<U>,
34 U: ?Sized + PartialOrd<Idx>,
35 {
36 open spec fn obeys_contains() -> bool {
37 (U::obeys_partial_cmp_spec() && <Idx as PartialOrdSpec<U>>::obeys_partial_cmp_spec())
38 }
39
40 open spec fn contains_spec(&self, i: &U) -> bool {
41 self@.start.is_le(&i) && if self@.exhausted {
42 i.is_lt(&self@.end)
43 } else {
44 i.is_le(&self@.end)
45 }
46 }
47}
48
49impl<Idx, U> ContainsSpec<Idx, U> for Range<Idx> where
50 Idx: PartialOrd<U>,
51 U: ?Sized + PartialOrd<Idx>,
52 {
53 open spec fn obeys_contains() -> bool {
54 (U::obeys_partial_cmp_spec() && <Idx as PartialOrdSpec<U>>::obeys_partial_cmp_spec())
55 }
56
57 open spec fn contains_spec(&self, i: &U) -> bool {
58 self.start.is_le(&i) && i.is_lt(&self.end)
59 }
60}
61
62impl<Idx> View for RangeInclusive<Idx> {
63 type V = RangeInclusiveView<Idx>;
64
65 uninterp spec fn view(&self) -> Self::V;
66}
67
68pub uninterp spec fn spec_range_next<A>(a: Range<A>) -> (Range<A>, Option<A>);
69
70pub assume_specification<Idx: PartialOrd<Idx>, U>[ Range::<Idx>::contains ](
75 r: &Range<Idx>,
76 i: &U,
77) -> (ret: bool) where Idx: PartialOrd<U>, U: ?Sized + PartialOrd<Idx>
78 ensures
79 <Range::<Idx> as ContainsSpec<Idx, U>>::obeys_contains() ==> ret == r.contains_spec(i),
80;
81
82pub assume_specification<Idx: PartialOrd<Idx>, U>[ RangeInclusive::<Idx>::contains ](
83 r: &RangeInclusive<Idx>,
84 i: &U,
85) -> (ret: bool) where Idx: PartialOrd<U>, U: ?Sized + PartialOrd<Idx>
86 ensures
87 <RangeInclusive::<Idx> as ContainsSpec<Idx, U>>::obeys_contains() ==> ret
88 == r.contains_spec(i),
89;
90
91pub assume_specification<Idx>[ RangeInclusive::<Idx>::new ](start: Idx, end: Idx) -> (ret:
92 core::ops::RangeInclusive<Idx>)
93 ensures
94 ret@ == (RangeInclusiveView { start, end, exhausted: false }),
95;
96
97impl<A: core::iter::Step> super::iter::IteratorSpecImpl for Range<A> {
98 open spec fn obeys_prophetic_iter_laws(&self) -> bool {
99 true
100 }
101
102 open spec fn remaining(&self) -> Seq<Self::Item> {
103 let steps = self.start.spec_steps_between_int(self.end);
104 let len = if steps > 0 {
105 steps
106 } else {
107 0
108 };
109 Seq::new(len as nat, |i: int| self.start.spec_forward_checked_int(i).unwrap())
110 }
111
112 uninterp spec fn will_return_none(&self) -> bool;
113
114 open spec fn decrease(&self) -> Option<nat> {
115 Some(self.start.spec_steps_between_int(self.end) as nat)
116 }
117
118 open spec fn peek(&self, index: int) -> Option<Self::Item> {
119 if 0 <= index <= self.start.spec_steps_between_int(self.end) {
121 Some(self.start.spec_forward_checked_int(index).unwrap())
122 } else {
123 None
124 }
125 }
126}
127
128impl<A: core::iter::Step> super::iter::IteratorSpecImpl for RangeInclusive<A> {
129 open spec fn obeys_prophetic_iter_laws(&self) -> bool {
130 true
131 }
132
133 open spec fn remaining(&self) -> Seq<Self::Item> {
134 Seq::new(
135 (self@.start.spec_steps_between_int(self@.end) + 1) as nat,
136 |i: int| self@.start.spec_forward_checked_int(i).unwrap(),
137 )
138 }
139
140 uninterp spec fn will_return_none(&self) -> bool;
141
142 open spec fn decrease(&self) -> Option<nat> {
143 Some((self@.start.spec_steps_between_int(self@.end) + 1) as nat)
144 }
145
146 open spec fn peek(&self, index: int) -> Option<Self::Item> {
147 if 0 <= index <= self@.start.spec_steps_between_int(self@.end) + 1 {
148 Some(self@.start.spec_forward_checked_int(index).unwrap())
149 } else {
150 None
151 }
152 }
153}
154
155pub assume_specification<A: core::iter::Step>[ <Range<A> as Iterator>::next ](
156 range: &mut Range<A>,
157) -> (r: Option<A>)
158 ensures
159 (*final(range), r) == spec_range_next(*old(range)),
160;
161
162pub enum SpecBound<T> {
166 Included(T),
167 Excluded(T),
168 Unbounded,
169}
170
171pub open spec fn spec_bound<T>(bound: Bound<T>) -> SpecBound<T> {
173 match bound {
174 Bound::Included(value) => SpecBound::Included(value),
175 Bound::Excluded(value) => SpecBound::Excluded(value),
176 Bound::Unbounded => SpecBound::Unbounded,
177 }
178}
179
180pub open spec fn spec_bound_ref<'a, T>(bound: &'a Bound<T>) -> SpecBound<&'a T> {
182 match bound {
183 Bound::Included(value) => SpecBound::Included(value),
184 Bound::Excluded(value) => SpecBound::Excluded(value),
185 Bound::Unbounded => SpecBound::Unbounded,
186 }
187}
188
189#[verifier::external_type_specification]
190pub struct ExBound<T>(Bound<T>);
191
192#[verifier::external_type_specification]
193pub struct ExRangeFull(RangeFull);
194
195#[verifier::external_type_specification]
196#[verifier::reject_recursive_types(Idx)]
197pub struct ExRangeFrom<Idx>(RangeFrom<Idx>);
198
199#[verifier::external_type_specification]
200#[verifier::reject_recursive_types(Idx)]
201pub struct ExRangeTo<Idx>(RangeTo<Idx>);
202
203#[verifier::external_type_specification]
204#[verifier::reject_recursive_types(Idx)]
205pub struct ExRangeToInclusive<Idx>(RangeToInclusive<Idx>);
206
207pub assume_specification<'s, T>[ <Range<T> as RangeBounds<T>>::start_bound ](
211 range: &'s Range<T>,
212) -> (result: Bound<&'s T>)
213 ensures
214 spec_bound(result) == SpecBound::Included(&range.start),
215;
216
217pub assume_specification<'s, T>[ <Range<T> as RangeBounds<T>>::end_bound ](
218 range: &'s Range<T>,
219) -> (result: Bound<&'s T>)
220 ensures
221 spec_bound(result) == SpecBound::Excluded(&range.end),
222;
223
224pub assume_specification<'s, T: ?Sized>[ <RangeFull as RangeBounds<T>>::start_bound ](
225 range: &'s RangeFull,
226) -> (result: Bound<&'s T>)
227 ensures
228 spec_bound(result) == SpecBound::Unbounded,
229;
230
231pub assume_specification<'s, T: ?Sized>[ <RangeFull as RangeBounds<T>>::end_bound ](
232 range: &'s RangeFull,
233) -> (result: Bound<&'s T>)
234 ensures
235 spec_bound(result) == SpecBound::Unbounded,
236;
237
238pub assume_specification<'s, T>[ <RangeFrom<T> as RangeBounds<T>>::start_bound ](
239 range: &'s RangeFrom<T>,
240) -> (result: Bound<&'s T>)
241 ensures
242 spec_bound(result) == SpecBound::Included(&range.start),
243;
244
245pub assume_specification<'s, T>[ <RangeFrom<T> as RangeBounds<T>>::end_bound ](
246 range: &'s RangeFrom<T>,
247) -> (result: Bound<&'s T>)
248 ensures
249 spec_bound(result) == SpecBound::Unbounded,
250;
251
252pub assume_specification<'s, T>[ <RangeTo<T> as RangeBounds<T>>::start_bound ](
253 range: &'s RangeTo<T>,
254) -> (result: Bound<&'s T>)
255 ensures
256 spec_bound(result) == SpecBound::Unbounded,
257;
258
259pub assume_specification<'s, T>[ <RangeTo<T> as RangeBounds<T>>::end_bound ](
260 range: &'s RangeTo<T>,
261) -> (result: Bound<&'s T>)
262 ensures
263 spec_bound(result) == SpecBound::Excluded(&range.end),
264;
265
266pub assume_specification<'s, T>[ <RangeInclusive<T> as RangeBounds<T>>::start_bound ](
267 range: &'s RangeInclusive<T>,
268) -> (result: Bound<&'s T>)
269 ensures
270 spec_bound(result) == SpecBound::Included(&range@.start),
271;
272
273pub assume_specification<'s, T>[ <RangeInclusive<T> as RangeBounds<T>>::end_bound ](
274 range: &'s RangeInclusive<T>,
275) -> (result: Bound<&'s T>)
276 ensures
277 spec_bound(result) == SpecBound::Included(&range@.end),
278;
279
280pub assume_specification<'s, T>[ <RangeToInclusive<T> as RangeBounds<T>>::start_bound ](
281 range: &'s RangeToInclusive<T>,
282) -> (result: Bound<&'s T>)
283 ensures
284 spec_bound(result) == SpecBound::Unbounded,
285;
286
287pub assume_specification<'s, T>[ <RangeToInclusive<T> as RangeBounds<T>>::end_bound ](
288 range: &'s RangeToInclusive<T>,
289) -> (result: Bound<&'s T>)
290 ensures
291 spec_bound(result) == SpecBound::Included(&range.end),
292;
293
294pub assume_specification<'s, T>[ <(Bound<T>, Bound<T>) as RangeBounds<T>>::start_bound ](
295 range: &'s (Bound<T>, Bound<T>),
296) -> (result: Bound<&'s T>)
297 ensures
298 spec_bound(result) == spec_bound_ref(&range.0),
299;
300
301pub assume_specification<'s, T>[ <(Bound<T>, Bound<T>) as RangeBounds<T>>::end_bound ](
302 range: &'s (Bound<T>, Bound<T>),
303) -> (result: Bound<&'s T>)
304 ensures
305 spec_bound(result) == spec_bound_ref(&range.1),
306;
307
308#[verifier::external_trait_specification]
315#[verifier::external_trait_extension(RangeBoundsSpec via RangeBoundsSpecImpl)]
316pub trait ExRangeBounds<T: ?Sized> {
317 type ExternalTraitSpecificationFor: RangeBounds<T>;
318
319 spec fn spec_start_bound(&self) -> SpecBound<&T>;
320
321 spec fn spec_end_bound(&self) -> SpecBound<&T>;
322
323 fn start_bound(&self) -> Bound<&T>;
324
325 fn end_bound(&self) -> Bound<&T>;
326}
327
328impl<T> RangeBoundsSpecImpl<T> for Range<T> {
329 open spec fn spec_start_bound(&self) -> SpecBound<&T> {
330 SpecBound::Included(&self.start)
331 }
332
333 open spec fn spec_end_bound(&self) -> SpecBound<&T> {
334 SpecBound::Excluded(&self.end)
335 }
336}
337
338impl<T: ?Sized> RangeBoundsSpecImpl<T> for RangeFull {
339 open spec fn spec_start_bound(&self) -> SpecBound<&T> {
340 SpecBound::Unbounded
341 }
342
343 open spec fn spec_end_bound(&self) -> SpecBound<&T> {
344 SpecBound::Unbounded
345 }
346}
347
348impl<T> RangeBoundsSpecImpl<T> for RangeFrom<T> {
349 open spec fn spec_start_bound(&self) -> SpecBound<&T> {
350 SpecBound::Included(&self.start)
351 }
352
353 open spec fn spec_end_bound(&self) -> SpecBound<&T> {
354 SpecBound::Unbounded
355 }
356}
357
358impl<T> RangeBoundsSpecImpl<T> for RangeTo<T> {
359 open spec fn spec_start_bound(&self) -> SpecBound<&T> {
360 SpecBound::Unbounded
361 }
362
363 open spec fn spec_end_bound(&self) -> SpecBound<&T> {
364 SpecBound::Excluded(&self.end)
365 }
366}
367
368impl<T> RangeBoundsSpecImpl<T> for RangeInclusive<T> {
369 open spec fn spec_start_bound(&self) -> SpecBound<&T> {
370 SpecBound::Included(&self@.start)
371 }
372
373 open spec fn spec_end_bound(&self) -> SpecBound<&T> {
374 SpecBound::Included(&self@.end)
375 }
376}
377
378impl<T> RangeBoundsSpecImpl<T> for RangeToInclusive<T> {
379 open spec fn spec_start_bound(&self) -> SpecBound<&T> {
380 SpecBound::Unbounded
381 }
382
383 open spec fn spec_end_bound(&self) -> SpecBound<&T> {
384 SpecBound::Included(&self.end)
385 }
386}
387
388impl<T> RangeBoundsSpecImpl<T> for (Bound<T>, Bound<T>) {
389 open spec fn spec_start_bound(&self) -> SpecBound<&T> {
390 spec_bound_ref(&self.0)
391 }
392
393 open spec fn spec_end_bound(&self) -> SpecBound<&T> {
394 spec_bound_ref(&self.1)
395 }
396}
397
398impl<'a, T: ?Sized + 'a> RangeBoundsSpecImpl<T> for (Bound<&'a T>, Bound<&'a T>) {
399 open spec fn spec_start_bound(&self) -> SpecBound<&T> {
400 match self.0 {
401 Bound::Included(start) => SpecBound::Included(start),
402 Bound::Excluded(start) => SpecBound::Excluded(start),
403 Bound::Unbounded => SpecBound::Unbounded,
404 }
405 }
406
407 open spec fn spec_end_bound(&self) -> SpecBound<&T> {
408 match self.1 {
409 Bound::Included(end) => SpecBound::Included(end),
410 Bound::Excluded(end) => SpecBound::Excluded(end),
411 Bound::Unbounded => SpecBound::Unbounded,
412 }
413 }
414}
415
416impl<T> RangeBoundsSpecImpl<T> for RangeFrom<&T> {
417 open spec fn spec_start_bound(&self) -> SpecBound<&T> {
418 SpecBound::Included(self.start)
419 }
420
421 open spec fn spec_end_bound(&self) -> SpecBound<&T> {
422 SpecBound::Unbounded
423 }
424}
425
426impl<T> RangeBoundsSpecImpl<T> for RangeTo<&T> {
427 open spec fn spec_start_bound(&self) -> SpecBound<&T> {
428 SpecBound::Unbounded
429 }
430
431 open spec fn spec_end_bound(&self) -> SpecBound<&T> {
432 SpecBound::Excluded(self.end)
433 }
434}
435
436impl<T> RangeBoundsSpecImpl<T> for Range<&T> {
437 open spec fn spec_start_bound(&self) -> SpecBound<&T> {
438 SpecBound::Included(self.start)
439 }
440
441 open spec fn spec_end_bound(&self) -> SpecBound<&T> {
442 SpecBound::Excluded(self.end)
443 }
444}
445
446impl<T> RangeBoundsSpecImpl<T> for RangeInclusive<&T> {
447 open spec fn spec_start_bound(&self) -> SpecBound<&T> {
448 SpecBound::Included(self@.start)
449 }
450
451 open spec fn spec_end_bound(&self) -> SpecBound<&T> {
452 SpecBound::Included(self@.end)
453 }
454}
455
456impl<T> RangeBoundsSpecImpl<T> for RangeToInclusive<&T> {
457 open spec fn spec_start_bound(&self) -> SpecBound<&T> {
458 SpecBound::Unbounded
459 }
460
461 open spec fn spec_end_bound(&self) -> SpecBound<&T> {
462 SpecBound::Included(self.end)
463 }
464}
465
466pub open spec fn slice_range_start<R: RangeBoundsSpec<usize>>(range: &R) -> int {
470 match range.spec_start_bound() {
471 SpecBound::Included(i) => *i as int,
472 SpecBound::Excluded(i) => (*i as int) + 1,
473 SpecBound::Unbounded => 0,
474 }
475}
476
477pub open spec fn slice_range_end<R: RangeBoundsSpec<usize>>(range: &R, len: nat) -> int {
481 match range.spec_end_bound() {
482 SpecBound::Included(i) => (*i as int) + 1,
483 SpecBound::Excluded(i) => *i as int,
484 SpecBound::Unbounded => len as int,
485 }
486}
487
488pub open spec fn slice_range_valid<R: RangeBoundsSpec<usize>>(range: &R, len: nat) -> bool {
491 slice_range_start(range) <= slice_range_end(range, len) <= len
492}
493
494} macro_rules! step_specs {
496 ($t: ty, $axiom: ident) => {
497 verus! {
498 impl StepSpecImpl for $t {
499 open spec fn spec_is_lt(self, other: Self) -> bool {
500 self < other
501 }
502 open spec fn spec_steps_between(self, end: Self) -> Option<usize> {
503 let n = end - self;
504 if usize::MIN <= n <= usize::MAX {
505 Some(n as usize)
506 } else {
507 None
508 }
509 }
510 open spec fn spec_steps_between_int(self, end: Self) -> int {
511 end - self
512 }
513 open spec fn spec_forward_checked(self, count: usize) -> Option<Self> {
514 StepSpec::spec_forward_checked_int(self, count as int)
515 }
516 open spec fn spec_forward_checked_int(self, count: int) -> Option<Self> {
517 if self + count <= $t::MAX {
518 Some((self + count) as $t)
519 } else {
520 None
521 }
522 }
523 open spec fn spec_backward_checked(self, count: usize) -> Option<Self> {
524 StepSpec::spec_backward_checked_int(self, count as int)
525 }
526 open spec fn spec_backward_checked_int(self, count: int) -> Option<Self> {
527 if self - count >= $t::MIN {
528 Some((self - count) as $t)
529 } else {
530 None
531 }
532 }
533 }
534 pub broadcast proof fn $axiom(range: Range<$t>)
537 ensures
538 StepSpec::spec_is_lt(range.start, range.end) ==>
539 (if let Some(n) = StepSpec::spec_forward_checked(range.start, 1) {
541 spec_range_next(range) == (Range { start: n, ..range }, Some(range.start))
542 } else {
543 true
544 }),
545 !StepSpec::spec_is_lt(range.start, range.end) ==>
546 #[trigger] spec_range_next(range) == (range, None::<$t>),
547 {
548 admit();
549 }
550 } };
552}
553
554step_specs!(u8, axiom_spec_range_next_u8);
555step_specs!(u16, axiom_spec_range_next_u16);
556step_specs!(u32, axiom_spec_range_next_u32);
557step_specs!(u64, axiom_spec_range_next_u64);
558step_specs!(u128, axiom_spec_range_next_u128);
559step_specs!(usize, axiom_spec_range_next_usize);
560step_specs!(i8, axiom_spec_range_next_i8);
561step_specs!(i16, axiom_spec_range_next_i16);
562step_specs!(i32, axiom_spec_range_next_i32);
563step_specs!(i64, axiom_spec_range_next_i64);
564step_specs!(i128, axiom_spec_range_next_i128);
565step_specs!(isize, axiom_spec_range_next_isize);
566
567verus! {
568
569pub broadcast group group_range_axioms {
570 axiom_spec_range_next_u8,
571 axiom_spec_range_next_u16,
572 axiom_spec_range_next_u32,
573 axiom_spec_range_next_u64,
574 axiom_spec_range_next_u128,
575 axiom_spec_range_next_usize,
576 axiom_spec_range_next_i8,
577 axiom_spec_range_next_i16,
578 axiom_spec_range_next_i32,
579 axiom_spec_range_next_i64,
580 axiom_spec_range_next_i128,
581 axiom_spec_range_next_isize,
582}
583
584}