Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions library/core/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3222,14 +3222,16 @@ pub const unsafe fn copysignf128(x: f128, y: f128) -> f128;
/// initialization state.
///
/// This is used for contracts only.
///
/// FIXME: Change this once we add support to quantifiers.
#[allow(dead_code)]
#[allow(unused_variables)]
fn check_copy_untyped<T>(src: *const T, dst: *mut T, count: usize) -> bool {
#[cfg(kani)]
if count > 0 {
// Inspect a non-deterministically chosen byte in the copy.
let byte = kani::any_where(|sz: &usize| *sz < size_of::<T>());
// Instead of checking each of the `count`-many copies, non-deterministically pick one of
// them and check it. Using quantifiers would not add value as we can rely on the solver to
// pick an uninitialized element if such an element exists.
let elem = kani::any_where(|val: &usize| *val < count);
let src_data = src as *const u8;
let dst_data = unsafe { dst.add(elem) } as *const u8;
Expand Down
13 changes: 4 additions & 9 deletions library/core/src/ptr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2242,9 +2242,8 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
}

// Checking if the answer should indeed be usize::MAX when a % stride != 0
// requires computing gcd(a, stride), which is too expensive without
// quantifiers (https://model-checking.github.io/kani/rfc/rfcs/0010-quantifiers.html).
// This should be updated once quantifiers are available.
// requires computing gcd(a, stride), which could be done using cttz as the implementation
// does.
if (a % stride != 0 && *result == usize::MAX) {
return true;
}
Expand Down Expand Up @@ -2275,12 +2274,8 @@ pub(crate) unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
/// Implementation of this function shall not panic. Ever.
#[safety::requires(m.is_power_of_two())]
#[safety::requires(x < m)]
// TODO: add ensures contract to check that the answer is indeed correct
// This will require quantifiers (https://model-checking.github.io/kani/rfc/rfcs/0010-quantifiers.html)
// so that we can add a precondition that gcd(x, m) = 1 like so:
// ∀d, d > 0 ∧ x % d = 0 ∧ m % d = 0 → d = 1
// With this precondition, we can then write this postcondition to check the correctness of the answer:
// #[safety::ensures(|result| wrapping_mul(*result, x) % m == 1)]
#[safety::requires(x % 2 != 0)]
#[safety::ensures(|result| wrapping_mul(*result, x) % m == 1)]
#[inline]
const unsafe fn mod_inv(x: usize, m: usize) -> usize {
/// Multiplicative modular inverse table modulo 2⁴ = 16.
Expand Down
7 changes: 3 additions & 4 deletions library/core/src/ptr/non_null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1434,10 +1434,9 @@ impl<T: PointeeSized> NonNull<T> {
if (align % stride == 0) && (self.pointer.addr() % stride != 0) {
return *result == usize::MAX;
}
// Checking if the answer should indeed be usize::MAX when align % stride != 0
// requires computing gcd(a, stride), which is too expensive without
// quantifiers (https://model-checking.github.io/kani/rfc/rfcs/0010-quantifiers.html).
// This should be updated once quantifiers are available.
// Checking if the answer should indeed be usize::MAX when a % stride != 0 requires
// computing gcd(align, stride), which could be done using cttz as the implementation of
// ptr::align_offset does.
if (align % stride != 0 && *result == usize::MAX) {
return true;
}
Expand Down
Loading