Skip to content

Commit 10299a4

Browse files
committed
iter: add kani proof for next_unchecked (#280)
Adds `kani` proof and function contract for `UncheckedIterator::next_unchecked`. Ensures that the safety invariants are held using the model checker.
1 parent 195e1b6 commit 10299a4

File tree

1 file changed

+20
-0
lines changed

1 file changed

+20
-0
lines changed

library/core/src/iter/traits/unchecked_iterator.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
use safety::requires;
2+
13
use crate::iter::TrustedLen;
4+
#[cfg(kani)]
5+
use crate::kani;
26

37
/// [`TrustedLen`] cannot have methods, so this allows augmenting it.
48
///
@@ -27,10 +31,26 @@ pub(crate) trait UncheckedIterator: TrustedLen {
2731
/// point you might want to implement this manually instead.
2832
#[unstable(feature = "trusted_len_next_unchecked", issue = "37572")]
2933
#[inline]
34+
#[requires(self.size_hint().0 != 0 && self.size_hint().1 != Some(0))]
35+
#[cfg_attr(kani, kani::modifies(self))]
3036
unsafe fn next_unchecked(&mut self) -> Self::Item {
3137
let opt = self.next();
3238
// SAFETY: The caller promised that we're not empty, and
3339
// `Self: TrustedLen` so we can actually trust the `size_hint`.
3440
unsafe { opt.unwrap_unchecked() }
3541
}
3642
}
43+
44+
#[cfg(kani)]
45+
#[kani::proof]
46+
fn verify_next_unchecked() {
47+
let arr: [u8; 1] = [kani::any(); 1];
48+
49+
let mut it = arr.iter();
50+
let (lo_hint, hi_hint) = it.size_hint();
51+
52+
kani::assume(lo_hint != 0);
53+
kani::assume(hi_hint != Some(0));
54+
55+
let _ = unsafe { it.next_unchecked() };
56+
}

0 commit comments

Comments
 (0)