Skip to content

Commit e68ac58

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 3bb48f0 commit e68ac58

File tree

1 file changed

+29
-1
lines changed

1 file changed

+29
-1
lines changed

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub(crate) trait UncheckedIterator: TrustedLen {
3131
/// point you might want to implement this manually instead.
3232
#[unstable(feature = "trusted_len_next_unchecked", issue = "37572")]
3333
#[inline]
34-
#[requires(self.size_hint().0 > 0)]
34+
#[requires(self.size_hint().0 != 0 && self.size_hint().1 != Some(0))]
3535
#[cfg_attr(kani, kani::modifies(self))]
3636
unsafe fn next_unchecked(&mut self) -> Self::Item {
3737
let opt = self.next();
@@ -40,3 +40,31 @@ pub(crate) trait UncheckedIterator: TrustedLen {
4040
unsafe { opt.unwrap_unchecked() }
4141
}
4242
}
43+
44+
#[cfg(kani)]
45+
#[kani::proof]
46+
fn verify_next_unchecked() {
47+
const N: usize = 1024;
48+
49+
let arr: [u8; N] = [kani::any(); N];
50+
51+
let idx = kani::any::<usize>() % (N - 1);
52+
53+
let mut it = arr[..=idx].iter();
54+
55+
let (lo, hi) = it.size_hint();
56+
57+
kani::assume(lo != 0);
58+
kani::assume(hi != Some(0));
59+
60+
let _ = unsafe { it.next_unchecked() };
61+
62+
let mut it = arr[idx..].iter();
63+
64+
let (lo, hi) = it.size_hint();
65+
66+
kani::assume(lo != 0);
67+
kani::assume(hi != Some(0));
68+
69+
let _ = unsafe { it.next_unchecked() };
70+
}

0 commit comments

Comments
 (0)