Skip to content

Commit

Permalink
Merge branch 'main' into attr-invariant
Browse files Browse the repository at this point in the history
  • Loading branch information
adpaco-aws committed Jul 30, 2024
2 parents 5847597 + 1553ae2 commit ae3f70b
Show file tree
Hide file tree
Showing 18 changed files with 241 additions and 5 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/verify-std-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jobs:
uses: actions/checkout@v4
with:
path: kani
fetch-depth: 0

- name: Setup Kani Dependencies
uses: ./kani/.github/actions/setup
Expand Down Expand Up @@ -79,8 +80,10 @@ jobs:
-Z mem-predicates -Z ptr-to-ref-cast-checks
- name: Compare PR results
if: steps.check-head.outcome != 'success' && steps.check-head.output != github.check-base.output
if: steps.check-head.outcome != 'success' && steps.check-head.outcome != steps.check-base.outcome
run: |
echo "New failure introduced by this change"
echo "HEAD: ${{ steps.check-head.outcome }}"
echo "BASE: ${{ steps.check-base.outcome }}"
exit 1
2 changes: 1 addition & 1 deletion kani-compiler/src/codegen_cprover_gotoc/utils/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub fn init() {

/// Custom panic hook to add more information when panic occurs during goto-c codegen.
#[allow(clippy::type_complexity)]
static DEFAULT_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
static DEFAULT_HOOK: LazyLock<Box<dyn Fn(&panic::PanicHookInfo<'_>) + Sync + Send + 'static>> =
LazyLock::new(|| {
let hook = panic::take_hook();
panic::set_hook(Box::new(|info| {
Expand Down
4 changes: 2 additions & 2 deletions kani-compiler/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const BUG_REPORT_URL: &str =

// Custom panic hook when running under user friendly message format.
#[allow(clippy::type_complexity)]
static PANIC_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
static PANIC_HOOK: LazyLock<Box<dyn Fn(&panic::PanicHookInfo<'_>) + Sync + Send + 'static>> =
LazyLock::new(|| {
let hook = panic::take_hook();
panic::set_hook(Box::new(|info| {
Expand All @@ -46,7 +46,7 @@ static PANIC_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 's

// Custom panic hook when executing under json error format `--error-format=json`.
#[allow(clippy::type_complexity)]
static JSON_PANIC_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
static JSON_PANIC_HOOK: LazyLock<Box<dyn Fn(&panic::PanicHookInfo<'_>) + Sync + Send + 'static>> =
LazyLock::new(|| {
let hook = panic::take_hook();
panic::set_hook(Box::new(|info| {
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
# SPDX-License-Identifier: Apache-2.0 OR MIT

[toolchain]
channel = "nightly-2024-07-21"
channel = "nightly-2024-07-30"
components = ["llvm-tools", "rustc-dev", "rust-src", "rustfmt"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
assertion\
- Status: SUCCESS\
- Description: "|_| im.x.get() < 101"\
in function modify

VERIFICATION:- SUCCESSFUL
25 changes: 25 additions & 0 deletions tests/expected/function-contract/interior-mutability/api/cell.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
// kani-flags: -Zfunction-contracts

/// Mutating Cell via `as_ptr` in contracts
use std::cell::Cell;

/// This struct contains Cell which can be mutated
struct InteriorMutability {
x: Cell<u32>,
}

#[kani::requires(im.x.get() < 100)]
#[kani::modifies(im.x.as_ptr())]
#[kani::ensures(|_| im.x.get() < 101)]
///im is an immutable reference with interior mutability
fn modify(im: &InteriorMutability) {
im.x.set(im.x.get() + 1)
}

#[kani::proof_for_contract(modify)]
fn harness_for_modify() {
let im: InteriorMutability = InteriorMutability { x: Cell::new(kani::any()) };
modify(&im)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
assertion\
- Status: SUCCESS\
- Description: "|_| old(im.x.get() + im.x.get()) == im.x.get()"\

assertion\
- Status: SUCCESS\
- Description: "|_| old(im.x.get() + im.x.get() + im.x.get() + im.x.get()) == im.x.get()"\

VERIFICATION:- SUCCESSFUL
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT
// kani-flags: -Zfunction-contracts

/// The objective of this test is to show that the contracts for double can be replaced as a stub within the contracts for quadruple.
/// This shows that we can generate `kani::any()` for Cell.
use std::cell::Cell;

/// This struct contains Cell which can be mutated
struct InteriorMutability {
x: Cell<u32>,
}

#[kani::ensures(|_| old(im.x.get() + im.x.get()) == im.x.get())]
#[kani::requires(im.x.get() < 100)]
#[kani::modifies(im.x.as_ptr())]
fn double(im: &InteriorMutability) {
im.x.set(im.x.get() + im.x.get())
}

#[kani::proof_for_contract(double)]
fn double_harness() {
let im: InteriorMutability = InteriorMutability { x: Cell::new(kani::any()) };
double(&im);
}

#[kani::ensures(|_| old(im.x.get() + im.x.get() + im.x.get() + im.x.get()) == im.x.get())]
#[kani::requires(im.x.get() < 50)]
#[kani::modifies(im.x.as_ptr())]
fn quadruple(im: &InteriorMutability) {
double(im);
double(im)
}

#[kani::proof_for_contract(quadruple)]
#[kani::stub_verified(double)]
fn quadruple_harness() {
let im: InteriorMutability = InteriorMutability { x: Cell::new(kani::any()) };
quadruple(&im);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
assertion\
- Status: SUCCESS\
- Description: "|_| unsafe{ *im.x.get() } < 101"\
in function modify

VERIFICATION:- SUCCESSFUL
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT
// kani-flags: -Zfunction-contracts

use std::cell::UnsafeCell;

/// This struct contains UnsafeCell which can be mutated
struct InteriorMutability {
x: UnsafeCell<u32>,
}

#[kani::requires(unsafe{*im.x.get()} < 100)]
#[kani::modifies(im.x.get())]
#[kani::ensures(|_| unsafe{*im.x.get()} < 101)]
/// `im` is an immutable reference with interior mutability
fn modify(im: &InteriorMutability) {
unsafe { *im.x.get() += 1 }
}

#[kani::proof_for_contract(modify)]
fn harness_for_modify() {
let im: InteriorMutability = InteriorMutability { x: UnsafeCell::new(kani::any()) };
modify(&im)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
assertion\
- Status: SUCCESS\
- Description: "|_| im.x.get() < 101"\
in function modify

VERIFICATION:- SUCCESSFUL
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
// kani-flags: -Zfunction-contracts

/// The objective of this test is to check the modification of a Cell used as interior mutability in an immutable struct
use std::cell::Cell;

/// This struct contains Cell which can be mutated
struct InteriorMutability {
x: Cell<u32>,
}

#[kani::requires(im.x.get() < 100)]
#[kani::modifies(&im.x)]
#[kani::ensures(|_| im.x.get() < 101)]
/// `im` is an immutable reference with interior mutability
fn modify(im: &InteriorMutability) {
im.x.set(im.x.get() + 1)
}

#[kani::proof_for_contract(modify)]
fn harness_for_modify() {
let im: InteriorMutability = InteriorMutability { x: Cell::new(kani::any()) };
modify(&im)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
assertion\
- Status: SUCCESS\
- Description: "|_| im.x.get().is_some()"\
in function modify

VERIFICATION:- SUCCESSFUL
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT
// kani-flags: -Zfunction-contracts

/// The objective of this test is to check the modification of an OnceCell used as interior mutability in an immutable struct
use std::cell::OnceCell;

/// This struct contains OnceCell which can be mutated
struct InteriorMutability {
x: OnceCell<u32>,
}

#[kani::requires(im.x.get().is_none())]
#[kani::modifies(&im.x)]
#[kani::ensures(|_| im.x.get().is_some())]
fn modify(im: &InteriorMutability) {
im.x.set(5).expect("")
}

#[kani::proof_for_contract(modify)]
fn harness_for_modify() {
let im: InteriorMutability = InteriorMutability { x: OnceCell::new() };
modify(&im)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
assertion\
- Status: SUCCESS\
- Description: "|_| unsafe{ *im.x.as_ptr() } < 101"\
in function modify

VERIFICATION:- SUCCESSFUL
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
// kani-flags: -Zfunction-contracts

/// The objective of this test is to check the modification of a RefCell used as interior mutability in an immutable struct
use std::cell::RefCell;

/// This struct contains Cell which can be mutated
struct InteriorMutability {
x: RefCell<u32>,
}

#[kani::requires(unsafe{*im.x.as_ptr()} < 100)]
#[kani::modifies(&im.x)]
#[kani::ensures(|_| unsafe{*im.x.as_ptr()} < 101)]
/// `im` is an immutable reference with interior mutability
fn modify(im: &InteriorMutability) {
im.x.replace_with(|&mut old| old + 1);
}

#[kani::proof_for_contract(modify)]
fn harness_for_modify() {
let im: InteriorMutability = InteriorMutability { x: RefCell::new(kani::any()) };
modify(&im)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
assertion\
- Status: SUCCESS\
- Description: "|_| unsafe{ *im.x.get() } < 101"\
in function modify

VERIFICATION:- SUCCESSFUL
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
// kani-flags: -Zfunction-contracts

/// The objective of this test is to check the modification of an UnsafeCell used as interior mutability in an immutable struct
use std::cell::UnsafeCell;

/// This struct contains UnsafeCell which can be mutated
struct InteriorMutability {
x: UnsafeCell<u32>,
}

#[kani::requires(unsafe{*im.x.get()} < 100)]
#[kani::modifies(im.x.get())]
#[kani::ensures(|_| unsafe{*im.x.get()} < 101)]
/// `im` is an immutable reference with interior mutability
fn modify(im: &InteriorMutability) {
unsafe { *im.x.get() += 1 }
}

#[kani::proof_for_contract(modify)]
fn harness_for_modify() {
let im: InteriorMutability = InteriorMutability { x: UnsafeCell::new(kani::any()) };
modify(&im)
}

0 comments on commit ae3f70b

Please sign in to comment.