Skip to content

Commit

Permalink
Merge branch 'main' into issue-3615
Browse files Browse the repository at this point in the history
  • Loading branch information
carolynzech authored Oct 24, 2024
2 parents 31cb24d + a8a28ee commit e1e8468
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 4 deletions.
147 changes: 147 additions & 0 deletions tests/kani/FunctionContracts/fixme_receiver_contracts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! Checks that function contracts work with different types of receivers. I.e.:
//! - &Self (i.e. &self)
//! - &mut Self (i.e &mut self)
//! - Box<Self>
//! - Rc<Self>
//! - Arc<Self>
//! - Pin<P> where P is one of the types above
//! Source: <https://doc.rust-lang.org/reference/items/traits.html?highlight=receiver#object-safety>
// compile-flags: --edition 2021
// kani-flags: -Zfunction-contracts

#![feature(rustc_attrs)]

extern crate kani;

use std::boxed::Box;
use std::pin::Pin;
use std::rc::Rc;
use std::sync::Arc;

/// Type representing a valid ASCII value going from `0..128`.
#[derive(Copy, Clone, PartialEq, Eq)]
#[rustc_layout_scalar_valid_range_start(0)]
#[rustc_layout_scalar_valid_range_end(128)]
struct CharASCII(u8);

impl kani::Arbitrary for CharASCII {
fn any() -> CharASCII {
let val = kani::any_where(|inner: &u8| *inner < 128);
unsafe { CharASCII(val) }
}
}

/// This type contains unsafe setter functions with the same contract but different type of
/// receivers.
impl CharASCII {
#[kani::modifies(&self.0)]
#[kani::requires(new_val < 128)]
#[kani::ensures(|_| self.0 == new_val)]
unsafe fn set_val(&mut self, new_val: u8) {
self.0 = new_val
}

#[kani::modifies(&self.0)]
#[kani::requires(new_val < 128)]
#[kani::ensures(|_| self.0 == new_val)]
unsafe fn set_mut_ref(self: &mut Self, new_val: u8) {
self.0 = new_val
}

#[kani::modifies(&self.as_ref().0)]
#[kani::requires(new_val < 128)]
#[kani::ensures(|_| self.as_ref().0 == new_val)]
unsafe fn set_box(mut self: Box<Self>, new_val: u8) {
self.as_mut().0 = new_val
}

#[kani::modifies(&self.as_ref().0)]
#[kani::requires(new_val < 128)]
#[kani::ensures(|_| self.as_ref().0 == new_val)]
unsafe fn set_rc(mut self: Rc<Self>, new_val: u8) {
Rc::<_>::get_mut(&mut self).unwrap().0 = new_val
}

#[kani::modifies(&self.as_ref().0)]
#[kani::requires(new_val < 128)]
#[kani::ensures(|_| self.as_ref().0 == new_val)]
unsafe fn set_arc(mut self: Arc<Self>, new_val: u8) {
Arc::<_>::get_mut(&mut self).unwrap().0 = new_val;
}

#[kani::modifies(&self.0)]
#[kani::requires(new_val < 128)]
#[kani::ensures(|_| self.0 == new_val)]
unsafe fn set_pin(mut self: Pin<&mut Self>, new_val: u8) {
self.0 = new_val
}

#[kani::modifies(&self.0)]
#[kani::requires(new_val < 128)]
#[kani::ensures(|_| self.0 == new_val)]
unsafe fn set_pin_box(mut self: Pin<Box<Self>>, new_val: u8) {
self.0 = new_val
}
}

mod verify {
use super::*;
use kani::Arbitrary;

#[kani::proof_for_contract(CharASCII::set_val)]
fn check_set_val() {
let mut obj = CharASCII::any();
let original = obj.0;
let new_val: u8 = kani::any();
unsafe { obj.set_val(new_val) };
}

#[kani::proof_for_contract(CharASCII::set_mut_ref)]
fn check_mut_ref() {
let mut obj = CharASCII::any();
let new_val: u8 = kani::any();
unsafe { obj.set_mut_ref(new_val) };
}

#[kani::proof_for_contract(CharASCII::set_box)]
fn check_box() {
let obj = CharASCII::any();
let original = obj.0;
let new_val: u8 = kani::any();
unsafe { Box::new(obj).set_box(new_val) };
}

#[kani::proof_for_contract(CharASCII::set_rc)]
fn check_rc() {
let obj = CharASCII::any();
let original = obj.0;
let new_val: u8 = kani::any();
unsafe { Rc::new(obj).set_rc(new_val) };
}

#[kani::proof_for_contract(CharASCII::set_arc)]
fn check_arc() {
let obj = CharASCII::any();
let original = obj.0;
let new_val: u8 = kani::any();
unsafe { Arc::new(obj).set_arc(new_val) };
}

#[kani::proof_for_contract(CharASCII::set_pin)]
fn check_pin() {
let mut obj = CharASCII::any();
let original = obj.0;
let new_val: u8 = kani::any();
unsafe { Pin::new(&mut obj).set_pin(new_val) };
}

#[kani::proof_for_contract(CharASCII::set_pin_box)]
fn check_pin_box() {
let obj = CharASCII::any();
let original = obj.0;
let new_val: u8 = kani::any();
unsafe { Pin::new(Box::new(obj)).set_pin_box(new_val) };
}
}
4 changes: 0 additions & 4 deletions tests/kani/FunctionContracts/fn_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ struct MyStruct {
#[kani::requires(val.u == tup_u)]
#[kani::requires(Ok(val.c) == char::try_from(first))]
#[kani::requires(val.c == tup_c)]
/// We need this extra clause due to <https://github.com/model-checking/kani/issues/3370>.
#[kani::requires(char::try_from(first).is_ok())]
pub fn odd_parameters_eq(
[first, second]: [u32; 2],
(tup_c, tup_u): (char, u32),
Expand All @@ -41,8 +39,6 @@ pub fn odd_parameters_eq(
#[kani::requires(val.u == tup_u)]
#[kani::requires(Ok(val.c) == char::try_from(first))]
// MISSING: #[kani::requires(val.c == tup_c)]
// We need this extra clause due to <https://github.com/model-checking/kani/issues/3370>.
#[kani::requires(char::try_from(first).is_ok())]
pub fn odd_parameters_eq_wrong(
[first, second]: [u32; 2],
(tup_c, tup_u): (char, u32),
Expand Down
25 changes: 25 additions & 0 deletions tests/kani/FunctionContracts/modify_slice_elem.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! Check that Kani correctly verifies the contract that modifies slices.
//!
//! Note that this test used to crash while parsing the annotations.
// kani-flags: -Zfunction-contracts
extern crate kani;

#[kani::requires(idx < slice.len())]
#[kani::modifies(slice.as_ptr().wrapping_add(idx))]
#[kani::ensures(|_| slice[idx] == new_val)]
fn modify_slice(slice: &mut [u32], idx: usize, new_val: u32) {
*slice.get_mut(idx).unwrap() = new_val;
}

#[cfg(kani)]
mod verify {
use super::modify_slice;

#[kani::proof_for_contract(modify_slice)]
fn check_modify_slice() {
let mut data = kani::vec::any_vec::<u32, 5>();
modify_slice(&mut data, kani::any(), kani::any())
}
}

0 comments on commit e1e8468

Please sign in to comment.