-
Notifications
You must be signed in to change notification settings - Fork 97
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a Kani function that checks if the range of a float is valid for …
…conversion to int
- Loading branch information
1 parent
0ebf089
commit e6067e9
Showing
10 changed files
with
174 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Copyright Kani Contributors | ||
// SPDX-License-Identifier: Apache-2.0 OR MIT | ||
|
||
//! This module contains functions useful for float-related checks | ||
#[macro_export] | ||
macro_rules! generate_float { | ||
($core:path) => { | ||
/// Returns whether the given float `value` satisfies the range | ||
/// condition of the `to_int_unchecked` methods, namely that the `value` | ||
/// after truncation is in range of the target `Int` | ||
/// | ||
/// # Example: | ||
/// | ||
/// ```no_run | ||
/// let f: f32 = 145.7; | ||
/// let fits_in_i8 = kani::float::float_to_int_in_range::<f32, i8>(f); | ||
/// // doesn't fit in `i8` because the value after truncation (`145.0`) is larger than `i8::MAX` | ||
/// assert!(!fits_in_i8); | ||
/// | ||
/// let f: f64 = 1e6; | ||
/// let fits_in_u32 = kani::float::float_to_int_in_range::<f64, u32>(f); | ||
/// // fits in `u32` because the value after truncation (`1e6`) is smaller than `u32::MAX` | ||
/// assert!(fits_in_u32); | ||
/// ``` | ||
#[kanitool::fn_marker = "FloatToIntInRangeHook"] | ||
pub fn float_to_int_in_range<Float, Int>(value: Float) -> bool { | ||
kani::kani_intrinsic() | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
error: Invalid type for first argument of `float_to_int_in_range` intrinsic. Expected a float type. Got `i32` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Copyright Kani Contributors | ||
// SPDX-License-Identifier: Apache-2.0 OR MIT | ||
|
||
//! This test checks that Kani emits an error when | ||
//! `kani::float::float_to_int_in_range` is instantiated with a non-float type | ||
#[kani::proof] | ||
fn check_invalid_float() { | ||
let i: i32 = 5; | ||
let _c = kani::float::float_to_int_in_range::<i32, u8>(i); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
error: Invalid type for second argument of `float_to_int_in_range` intrinsic. Expected an integer type. Got `bool` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Copyright Kani Contributors | ||
// SPDX-License-Identifier: Apache-2.0 OR MIT | ||
|
||
//! This test checks that Kani emits an error when | ||
//! `kani::float::float_to_int_in_range` is instantiated with a non-integer type | ||
#[kani::proof] | ||
fn check_invalid_integer() { | ||
let f: f32 = kani::any(); | ||
let _c = kani::float::float_to_int_in_range::<f32, bool>(f); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
||
//! This test checks that `kani::float::float_to_int_in_range` works as expected | ||
#[kani::proof] | ||
fn check_float_to_int_in_range() { | ||
let f: f32 = 5.6; | ||
let fits_in_u16 = kani::float::float_to_int_in_range::<f32, u16>(f); | ||
assert!(fits_in_u16); | ||
let i: u16 = unsafe { f.to_int_unchecked() }; | ||
assert_eq!(i, 5); | ||
|
||
let f: f32 = 145.7; | ||
let fits_in_i8 = kani::float::float_to_int_in_range::<f32, i8>(f); | ||
// doesn't fit in `i8` because the value after truncation (`145.0`) is larger than `i8::MAX` | ||
assert!(!fits_in_i8); | ||
|
||
let f: f64 = 1e6; | ||
let fits_in_u32 = kani::float::float_to_int_in_range::<f64, u32>(f); | ||
// fits in `u32` because the value after truncation (`1e6`) is smaller than `u32::MAX` | ||
assert!(fits_in_u32); | ||
let i: u32 = unsafe { f.to_int_unchecked() }; | ||
assert_eq!(i, 1_000_000); | ||
} |