Skip to content

Commit 32e0cf9

Browse files
Yenyun035yew005rajathkotyal
authored
Contracts and Harnesses for unchecked_neg (rust-lang#102)
Towards rust-lang#59 ### Changes * Added contracts for `unchecked_neg` (located in `library/core/src/num/int_macros.rs`) * Added a harness for `unchecked_neg` of each signed integer type * `i8`, `i16`, `i32`, `i64`, `i128`, `isize` --- 6 harnesses in total. * Fixed comments. ### Revalidation 1. Per the discussion in rust-lang#59, we have to **build and run Kani from `feature/verify-rust-std` branch**. 2. To revalidate the verification results, run the following command. `<harness_to_run>` can be either `num::verify` to run all harnesses or `num::verify::<harness_name>` (e.g. `check_unchecked_neg_i8`) to run a specific harness. ``` kani verify-std "path/to/library" \ --harness <harness_to_run> \ -Z unstable-options \ -Z function-contracts \ -Z mem-predicates ``` All default harnesses should pass. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses. --------- Co-authored-by: yew005 <[email protected]> Co-authored-by: Rajath Kotyal <[email protected]> Co-authored-by: rajathmCMU <[email protected]>
1 parent 0de4670 commit 32e0cf9

File tree

2 files changed

+30
-9
lines changed

2 files changed

+30
-9
lines changed

library/core/src/num/int_macros.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,8 @@ macro_rules! int_impl {
11671167
#[rustc_const_unstable(feature = "unchecked_neg", issue = "85122")]
11681168
#[inline(always)]
11691169
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1170+
#[requires(self != $SelfT::MIN)]
1171+
#[ensures(|result| *result == -self)]
11701172
pub const unsafe fn unchecked_neg(self) -> Self {
11711173
assert_unsafe_precondition!(
11721174
check_language_ub,

library/core/src/num/mod.rs

+28-9
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
use crate::str::FromStr;
66
use crate::ub_checks::assert_unsafe_precondition;
77
use crate::{ascii, intrinsics, mem};
8-
use safety::requires;
8+
use safety::{requires, ensures};
99

1010
#[cfg(kani)]
1111
use crate::kani;
@@ -1661,11 +1661,11 @@ mod verify {
16611661
// `unchecked_add` proofs
16621662
//
16631663
// Target types:
1664-
// i{8,16,32,64,128} and u{8,16,32,64,128} -- 10 types in total
1664+
// i{8,16,32,64,128,size} and u{8,16,32,64,128,size} -- 12 types in total
16651665
//
16661666
// Target contracts:
1667-
//#[requires(!self.overflowing_sub(rhs).1)] // Preconditions: No overflow should occur
1668-
//#[ensures(|ret| *ret >= Self::MIN && *ret <= Self::MAX)] // Postconditions: Result must be within valid bounds
1667+
// Preconditions: No overflow should occur
1668+
// #[requires(!self.overflowing_add(rhs).1)]
16691669
//
16701670
// Target function:
16711671
// pub const unsafe fn unchecked_add(self, rhs: Self) -> Self
@@ -1682,12 +1682,31 @@ mod verify {
16821682
generate_unchecked_math_harness!(u128, unchecked_add, checked_unchecked_add_u128);
16831683
generate_unchecked_math_harness!(usize, unchecked_add, checked_unchecked_add_usize);
16841684

1685+
// `unchecked_neg` proofs
1686+
//
1687+
// Target types:
1688+
// i{8,16,32,64,128,size} -- 6 types in total
1689+
//
1690+
// Target contracts:
1691+
// #[requires(self != $SelfT::MIN)]
1692+
//
1693+
// Target function:
1694+
// pub const unsafe fn unchecked_neg(self) -> Self
1695+
generate_unchecked_neg_harness!(i8, checked_unchecked_neg_i8);
1696+
generate_unchecked_neg_harness!(i16, checked_unchecked_neg_i16);
1697+
generate_unchecked_neg_harness!(i32, checked_unchecked_neg_i32);
1698+
generate_unchecked_neg_harness!(i64, checked_unchecked_neg_i64);
1699+
generate_unchecked_neg_harness!(i128, checked_unchecked_neg_i128);
1700+
generate_unchecked_neg_harness!(isize, checked_unchecked_neg_isize);
1701+
16851702
// unchecked_mul proofs
16861703
//
16871704
// Target types:
1688-
// i{8,16,32,64,128, size} and u{8,16,32,64,128, size} -- 36 types in total
1705+
// i{8,16,32,64,128,size} and u{8,16,32,64,128,size} -- 12 types in total, with different interval checks for each.
1706+
// Total types of checks including intervals -- 36
16891707
//
16901708
// Target contracts:
1709+
// Preconditions: No overflow should occur
16911710
// #[requires(!self.overflowing_mul(rhs).1)]
16921711
//
16931712
// Target function:
@@ -1783,11 +1802,10 @@ mod verify {
17831802
// `unchecked_shl` proofs
17841803
//
17851804
// Target types:
1786-
// i{8,16,32,64,128} and u{8,16,32,64,128} -- 12 types in total
1805+
// i{8,16,32,64,128,size} and u{8,16,32,64,128,size} -- 12 types in total
17871806
//
17881807
// Target contracts:
17891808
// #[requires(shift < Self::BITS)]
1790-
// #[ensures(|ret| *ret == self << shift)]
17911809
//
17921810
// Target function:
17931811
// pub const unsafe fn unchecked_shl(self, shift: u32) -> Self
@@ -1809,10 +1827,11 @@ mod verify {
18091827
// `unchecked_sub` proofs
18101828
//
18111829
// Target types:
1812-
// i{8,16,32,64,128} and u{8,16,32,64,128} -- 12 types in total
1830+
// i{8,16,32,64,128,size} and u{8,16,32,64,128,size} -- 12 types in total
18131831
//
18141832
// Target contracts:
1815-
// #[requires(!self.overflowing_sub(rhs).1)] // Preconditions: No overflow should occur
1833+
// Preconditions: No overflow should occur
1834+
// #[requires(!self.overflowing_sub(rhs).1)]
18161835
//
18171836
// Target function:
18181837
// pub const unsafe fn unchecked_sub(self, rhs: Self) -> Self

0 commit comments

Comments
 (0)