diff --git a/library/kani/src/contracts.rs b/library/kani/src/contracts.rs index beddd7cc580e..2dc2bd2a4957 100644 --- a/library/kani/src/contracts.rs +++ b/library/kani/src/contracts.rs @@ -25,7 +25,7 @@ //! simple division function `my_div`: //! //! ``` -//! fn my_div(dividend: u32, divisor: u32) -> u32 { +//! fn my_div(dividend: usize, divisor: usize) -> usize { //! dividend / divisor //! } //! ``` @@ -35,8 +35,12 @@ //! allows us to declare constraints on what constitutes valid inputs to our //! function. In this case we would want to disallow a divisor that is `0`. //! -//! ```ignore +//! ``` +//! # use kani::requires; //! #[requires(divisor != 0)] +//! # fn my_div(dividend: usize, divisor: usize) -> usize { +//! # dividend / divisor +//! # } //! ``` //! //! This is called a precondition, because it is enforced before (pre-) the @@ -51,7 +55,11 @@ //! approximation of the result of division for instance could be this: //! //! ``` -//! #[ensures(|result : &u32| *result <= dividend)] +//! # use kani::ensures; +//! #[ensures(|result : &usize| *result <= dividend)] +//! # fn my_div(dividend: usize, divisor: usize) -> usize { +//! # dividend / divisor +//! # } //! ``` //! //! This is called a postcondition and it also has access to the arguments and @@ -66,9 +74,11 @@ //! order does not matter. In our example putting them together looks like this: //! //! ``` -//! #[kani::requires(divisor != 0)] -//! #[kani::ensures(|result : &u32| *result <= dividend)] -//! fn my_div(dividend: u32, divisor: u32) -> u32 { +//! use kani::{requires, ensures}; +//! +//! #[requires(divisor != 0)] +//! #[ensures(|result : &usize| *result <= dividend)] +//! fn my_div(dividend: usize, divisor: usize) -> usize { //! dividend / divisor //! } //! ``` @@ -84,9 +94,18 @@ //! function we want to check. //! //! ``` +//! # use kani::{requires, ensures}; +//! # +//! # #[requires(divisor != 0)] +//! # #[ensures(|result : &usize| *result <= dividend)] +//! # fn my_div(dividend: usize, divisor: usize) -> usize { +//! # dividend / divisor +//! # } +//! # //! #[kani::proof_for_contract(my_div)] //! fn my_div_harness() { -//! my_div(kani::any(), kani::any()) } +//! my_div(kani::any(), kani::any()); +//! } //! ``` //! //! The harness is checked like any other by running `cargo kani` and can be @@ -104,10 +123,18 @@ //! the contract will be used automatically. //! //! ``` +//! # use kani::{requires, ensures}; +//! # +//! # #[requires(divisor != 0)] +//! # #[ensures(|result : &usize| *result <= dividend)] +//! # fn my_div(dividend: usize, divisor: usize) -> usize { +//! # dividend / divisor +//! # } +//! # //! #[kani::proof] //! #[kani::stub_verified(my_div)] //! fn use_div() { -//! let v = vec![...]; +//! let v = kani::vec::any_vec::(); //! let some_idx = my_div(v.len() - 1, 3); //! v[some_idx]; //! } diff --git a/library/kani/src/invariant.rs b/library/kani/src/invariant.rs index 068cdedc277e..d52d2f8e3572 100644 --- a/library/kani/src/invariant.rs +++ b/library/kani/src/invariant.rs @@ -39,6 +39,14 @@ /// ``` /// You can specify its safety invariant as: /// ```rust +/// # #[derive(kani::Arbitrary)] +/// # pub struct MyDate { +/// # day: u8, +/// # month: u8, +/// # year: i64, +/// # } +/// # fn days_in_month(_: i64, _: u8) -> u8 { 31 } +/// /// impl kani::Invariant for MyDate { /// fn is_safe(&self) -> bool { /// self.month > 0 @@ -49,12 +57,33 @@ /// } /// ``` /// And use it to check that your APIs are safe: -/// ```rust +/// ```no_run +/// # use kani::Invariant; +/// # +/// # #[derive(kani::Arbitrary)] +/// # pub struct MyDate { +/// # day: u8, +/// # month: u8, +/// # year: i64, +/// # } +/// # +/// # fn days_in_month(_: i64, _: u8) -> u8 { todo!() } +/// # fn increase_date(_: &mut MyDate, _: u8) { todo!() } +/// # +/// # impl kani::Invariant for MyDate { +/// # fn is_safe(&self) -> bool { +/// # self.month > 0 +/// # && self.month <= 12 +/// # && self.day > 0 +/// # && self.day <= days_in_month(self.year, self.month) +/// # } +/// # } +/// # /// #[kani::proof] /// fn check_increase_date() { /// let mut date: MyDate = kani::any(); /// // Increase date by one day -/// increase_date(date, 1); +/// increase_date(&mut date, 1); /// assert!(date.is_safe()); /// } /// ``` diff --git a/library/kani/src/lib.rs b/library/kani/src/lib.rs index c3e9ae5497cc..e2557ad10124 100644 --- a/library/kani/src/lib.rs +++ b/library/kani/src/lib.rs @@ -19,6 +19,8 @@ #![feature(ptr_metadata)] #![feature(f16)] #![feature(f128)] +// Need to add this since we are deprecating `kani::check`. Remove this when we remove that API. +#![allow(deprecated)] // Allow us to use `kani::` to access crate features. extern crate self as kani; diff --git a/library/kani/src/shadow.rs b/library/kani/src/shadow.rs index a7ea57c6fd40..48ce8f0f9211 100644 --- a/library/kani/src/shadow.rs +++ b/library/kani/src/shadow.rs @@ -10,7 +10,7 @@ //! //! # Example //! -//! ``` +//! ```no_run //! use kani::shadow::ShadowMem; //! use std::alloc::{alloc, Layout}; //! diff --git a/library/kani/src/slice.rs b/library/kani/src/slice.rs index 1b13de29d589..c419a881fa55 100644 --- a/library/kani/src/slice.rs +++ b/library/kani/src/slice.rs @@ -9,7 +9,8 @@ use crate::{any, assume}; /// /// # Example: /// -/// ```rust +/// ```no_run +/// # fn foo(_: &[i32]) {} /// let arr = [1, 2, 3]; /// let slice = kani::slice::any_slice_of_array(&arr); /// foo(slice); // where foo is a function that takes a slice and verifies a property about it diff --git a/library/kani_core/src/lib.rs b/library/kani_core/src/lib.rs index 5df8f2228c62..dbb8df1822b7 100644 --- a/library/kani_core/src/lib.rs +++ b/library/kani_core/src/lib.rs @@ -85,7 +85,7 @@ macro_rules! kani_intrinsics { /// /// The code snippet below should never panic. /// - /// ```rust + /// ```no_run /// let i : i32 = kani::any(); /// kani::assume(i > 10); /// if i < 0 { @@ -95,7 +95,7 @@ macro_rules! kani_intrinsics { /// /// The following code may panic though: /// - /// ```rust + /// ```no_run /// let i : i32 = kani::any(); /// assert!(i < 0, "This may panic and verification should fail."); /// kani::assume(i > 10); @@ -118,7 +118,7 @@ macro_rules! kani_intrinsics { /// /// # Example: /// - /// ```rust + /// ```no_run /// let x: bool = kani::any(); /// let y = !x; /// kani::assert(x || y, "ORing a boolean variable with its negation must be true") @@ -138,18 +138,33 @@ macro_rules! kani_intrinsics { assert!(cond, "{}", msg); } - /// Creates an assertion of the specified condition and message, but does not assume it afterwards. + /// Creates a non-fatal property with the specified condition and message. + /// + /// This check will not impact the program control flow even when it fails. /// /// # Example: /// - /// ```rust + /// ```no_run /// let x: bool = kani::any(); /// let y = !x; - /// kani::check(x || y, "ORing a boolean variable with its negation must be true") + /// kani::check(x || y, "ORing a boolean variable with its negation must be true"); + /// kani::check(x == y, "A boolean variable is always different than its negation"); + /// kani::cover!(true, "This should still be reachable"); /// ``` + /// + /// # Deprecated + /// + /// This function was meant to be internal only, and it was added to Kani's public interface + /// by mistake. Thus, it will be made private in future releases. + /// Instead, we recommend users to either use `assert` or `cover` to create properties they + /// would like to verify. #[cfg(not(feature = "concrete_playback"))] #[inline(never)] #[rustc_diagnostic_item = "KaniCheck"] + // TODO: Remove the `#![allow(deprecated)]` inside kani's crate once this is made private. + #[cfg_attr(not(feature = "no_core"), deprecated(since="0.55.0", + note="This API was accidently added as a public function and it will be made private in \ + future releases."))] pub const fn check(cond: bool, msg: &'static str) { let _ = cond; let _ = msg; @@ -158,6 +173,9 @@ macro_rules! kani_intrinsics { #[cfg(feature = "concrete_playback")] #[inline(never)] #[rustc_diagnostic_item = "KaniCheck"] + #[deprecated(since="0.55.0", + note="This API was accidently added as a public function and it will be made private in \ + future releases.")] pub const fn check(cond: bool, msg: &'static str) { assert!(cond, "{}", msg); } @@ -166,7 +184,11 @@ macro_rules! kani_intrinsics { /// /// # Example: /// - /// ```rust + /// ```no_run + /// # use crate::kani; + /// # + /// # let array: [u8; 10] = kani::any(); + /// # let slice = kani::slice::any_slice_of_array(&array); /// kani::cover(slice.len() == 0, "The slice may have a length of 0"); /// ``` /// @@ -193,7 +215,11 @@ macro_rules! kani_intrinsics { /// In the snippet below, we are verifying the behavior of the function `fn_under_verification` /// under all possible `NonZeroU8` input values, i.e., all possible `u8` values except zero. /// - /// ```rust + /// ```no_run + /// # use std::num::NonZeroU8; + /// # use crate::kani; + /// # + /// # fn fn_under_verification(_: NonZeroU8) {} /// let inputA = kani::any::(); /// fn_under_verification(inputA); /// ``` @@ -231,7 +257,11 @@ macro_rules! kani_intrinsics { /// In the snippet below, we are verifying the behavior of the function `fn_under_verification` /// under all possible `u8` input values between 0 and 12. /// - /// ```rust + /// ```no_run + /// # use std::num::NonZeroU8; + /// # use crate::kani; + /// # + /// # fn fn_under_verification(_: u8) {} /// let inputA: u8 = kani::any_where(|x| *x < 12); /// fn_under_verification(inputA); /// ``` diff --git a/scripts/kani-regression.sh b/scripts/kani-regression.sh index bd6b04d7386e..be2548235ce6 100755 --- a/scripts/kani-regression.sh +++ b/scripts/kani-regression.sh @@ -41,8 +41,8 @@ cargo test -p cprover_bindings cargo test -p kani-compiler cargo test -p kani-driver cargo test -p kani_metadata -# skip doc tests and enable assertions to fail -cargo test -p kani --lib --features concrete_playback +# Use concrete playback to enable assertions failure +cargo test -p kani --features concrete_playback # Test the actual macros, skipping doc tests and enabling extra traits for "syn" # so we can debug print AST RUSTFLAGS=--cfg=kani_sysroot cargo test -p kani_macros --features syn/extra-traits --lib diff --git a/tests/ui/check_deprecated/deprecated_warning.expected b/tests/ui/check_deprecated/deprecated_warning.expected new file mode 100644 index 000000000000..851d7bffb27a --- /dev/null +++ b/tests/ui/check_deprecated/deprecated_warning.expected @@ -0,0 +1 @@ +warning: use of deprecated function `kani::check`: This API was accidently added as a public function and it will be made private in future releases. diff --git a/tests/ui/check_deprecated/deprecated_warning.rs b/tests/ui/check_deprecated/deprecated_warning.rs new file mode 100644 index 000000000000..f3d791256081 --- /dev/null +++ b/tests/ui/check_deprecated/deprecated_warning.rs @@ -0,0 +1,10 @@ +// Copyright Kani Contributors +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// kani-flags: --only-codegen + +/// Ensure that Kani prints a deprecation warning if users invoke `kani::check`. +#[kani::proof] +fn internal_api() { + kani::check(kani::any(), "oops"); +}