Uh oh!
There was an error while loading. Please reload this page.
Contracts & Harnesses for f{32,64}::to_int_unchecked - #134
Conversation
…-0011-core-nums-yenyunw-f32-to-int-unchecked
f32::to_int_uncheckedto_int_unchecked…-0011-core-nums-yenyunw-f32-to-int-unchecked
@celinval@carolynzech@zhassan-aws@feliperodri I was able to run f32->i8 harness. One of the checks failed, and I guess it is because the contract is incorrect. Specifically, I think the My confusion is, how can I refer to the max/min of the resulting integer type given that the type parameters accessible from the context of the contract are |
Yenyun035
commented
Nov 9, 2024
I found this workaround, inspired by this TypeChecker, and was able to run the f32->i8 harness (see here for unreachables). It took a while (~1.5 minutes) after compilation ( While this workaround might work, I think it would be too messy in the end. I'm wondering if it's possible to have a macro generating functions that check if the float value is in the bound of an integer type, as shown in the example below. However, I think it might cause circular dependency. If there is no better way to make the contract cleaner, maybe we could still proceed with the aforementioned approach. use core::any::type_name;// Not sure where to place; Not sure if this works.macro_rules! generate_is_in_range_check {($floatType:ty, $($intType:ty, $intStr:expr),+) => {
$(pubfn is_in_range<Int>(num: $floatType) -> bool{
type_name::<$intType>().contains($intStr) && num >= <$intType>::MINas $floatType && num <= <$intType>::MAXas $floatType
})+
}}generate_is_in_range_check!(f32,i8,"i8");Then the contract becomes:#[requires(self.is_finite() && is_in_range::<Int>(self))]By the way, I also tried the @celinval@carolynzech@zhassan-aws@feliperodri I would appreciate any ideas and advice! |
zhassan-aws
commented
Nov 10, 2024
I think you should be able to define a macro that matches on the macro_rules! foo {(u8, ...) => { ... }(u16, ...) => { ... }
....}and use it in the contract. |
@feliperodri Thank you for your response! I tried this approach by adding the macro in // mod.rspubmod verify {macro_rules! is_in_range {(i8, $floatType:ty, $num:ident) => { $num >= i8::MINas $floatType && $num <= i8::MAXas $floatType };(i16, $floatType:ty, $num:ident) => { $num >= i16::MINas $floatType && $num <= i16::MAXas $floatType };(i32, $floatType:ty, $num:ident) => { $num >= i32::MINas $floatType && $num <= i32::MAXas $floatType };(i64, $floatType:ty, $num:ident) => { $num >= i64::MINas $floatType && $num <= i64::MAXas $floatType };(i128, $floatType:ty, $num:ident) => { $num >= i128::MINas $floatType && $num <= i128::MAXas $floatType };(isize, $floatType:ty, $num:ident) => { $num >= isize::MINas $floatType && $num <= isize::MAXas $floatType };(u8, $floatType:ty, $num:ident) => { $num >= u8::MINas $floatType && $num <= u8::MAXas $floatType };(u16, $floatType:ty, $num:ident) => { $num >= u16::MINas $floatType && $num <= u16::MAXas $floatType };(u32, $floatType:ty, $num:ident) => { $num >= u32::MINas $floatType && $num <= u32::MAXas $floatType };(u64, $floatType:ty, $num:ident) => { $num >= u64::MINas $floatType && $num <= u64::MAXas $floatType };(u128, $floatType:ty, $num:ident) => { $num >= u128::MINas $floatType && $num <= u128::MAXas $floatType };(usize, $floatType:ty, $num:ident) => { $num >= usize::MINas $floatType && $num <= usize_isize_to_xe_bytes_doc::MAXas $floatType };}pub(crate)use is_in_range;}// Call in to_int_unchecked contract (f32.rs)usesuper::num::verify::is_in_range;#[requires(self.is_finite() && is_in_range!(Int,Self,self))]// Result
error: no rules expected `Int`
--> /path/to/repo/vrs/library/core/src/num/f32.rs:1076:49
|
1076 | #[requires(self.is_finite() && is_in_range!(Int,Self,self))]
| ^^^ no rules expected this token in macro call
|
::: /path/to/repo/vrs/library/core/src/num/mod.rs:1693:5
|
1693 | macro_rules! is_in_range {
| ------------------------ when calling this macro
|
note:while trying to match `i8`
--> /path/to/repo/vrs/library/core/src/num/mod.rs:1694:10
|
1694 | (i8, $floatType:ty, $num:ident) => { $num >= i8::MINas $floatType && $num <= i8::MAXas $floatType };
| |
zhassan-aws
commented
Nov 12, 2024
I see. The other alternative I could think of is to define a trait that provides |
zhassan-aws
commented
Nov 12, 2024
There's also the issue of imprecision when casting an int value to a float. For instance, Not sure what the best approach here is. Both MIRI and (now) Kani have their own internal methods to check if the values are in range (e.g. see rust-lang/miri#1325). I wonder whether those can be somehow exposed in the library. Ideally, there should be a |
Yenyun035
commented
Nov 12, 2024
Thank you for pointing this out! We will pay attention to it.
Thank you for sharing this. Is it possible to have Kani support this? E.g. expose an Thank you! @zhassan-aws |
zhassan-aws
commented
Nov 12, 2024
Yes, I think it would be possible. This would likely need to be done through providing a trait and its implementation for different float types so that it can be used with the generic |
Yenyun035
commented
Nov 12, 2024
@zhassan-aws I just filed this Feature Request. Thank you! |
celinval
commented
Nov 30, 2024
Hi @Yenyun035, we have updated the Kani version in this repo. You should be able to use the new API |
@celinval Thank you! I have run Kani on all harnesses and updated the results in the above. It's ready for review now 👍 To compile, we need to add the |
celinval
commented
Dec 2, 2024
Can you please add that to verify-rust-std/scripts/run-kani.sh Lines 214 to 216 in 7e8a03d |
Uh oh!
There was an error while loading. Please reload this page.
@celinval@tautschnig@carolynzech@feliperodri Could you please review this PR and #163 as well? Thank you! |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Yenyun035
commented
Dec 3, 2024
@zhassan-aws Thank you. Fixed. |
Yenyun035
commented
Dec 3, 2024
I found one of the checks failed due to the above error, but the function is indeed used in the contract: #[requires(self.is_finite() && float_to_int_in_range::<Self,Int>(self))] |
zhassan-aws
commented
Dec 3, 2024
Try putting the import under |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Towards #59
(Resolved) Depends on this Kani Issue and this PR, as discussed in this thread in #59
(Resolved) Depends on this Kani Issue and this PR
(Resolved) Waiting for Kani PR#3742 merged into
feature/verify-rust-stdf16 and f128 are in #163
Changes
f{32,64}::to_int_unchecked(located inlibrary/core/src/num/f{32,64}.rs)to_int_uncheckedharnessesf{32,64}to_int_uncheckedof each integer typei8,i16,i32,i64,i128,isize,u8,u16,u32,u64,u128,usize--- 12 harnesses in total.Verification Results
To compile, we need to add the
-Z float-libflag.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.