-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Recursion unwinding does not terminate #3771
Comments
Thanks for the report, @thanhnguyen-aws! Have you tried
You would have to annotate the recursive function with contracts. |
@feliperodri The |
Apparently, this occurs because of an exponential blow-up in the recursion tree? Here's a simpler reproducer: fn rec(n: u8) -> u8 {
if n == 0 {
return 0;
}
//if n > 10 {
// return rec(n - 1);
//}
return rec(n - 1);
}
#[kani::proof]
#[kani::unwind(256)]
fn main() {
let n: u8 = kani::any();
let z = rec(n);
assert!(z == 0);
} This terminates immediately: $ kani iss3771.rs
...
SUMMARY:
** 0 of 3 failed
VERIFICATION:- SUCCESSFUL
Verification Time: 0.57622415s but if I enable the commented-out code (which doesn't change the semantics of the function), CBMC keeps unwinding for more than 10 minutes without terminating:
@tautschnig do you think there's anything that can be done here? |
@thanhnguyen-aws You can work around the issue by rewriting fn gcd_rec(x: u8, y: u8) -> u8 {
if y == 0 {
x
} else if x == 0 {
y
} else {
let mut x = x;
let mut y = y;
if y > x {
let temp = x;
x = y;
y = temp;
}
gcd_rec(y, x - y)
}
} With that, verification terminates successfully in ~1 minute:
|
@feliperodri @zhassan-aws Thank you very much for your response. |
I ran a small experiment to check the equivalence of the two versions of the greatest-common-divisor function, one is written with a loop and one in recursion.
I tried this code:
using the following command line invocation:
with Kani version: 0.56.0
I expected to see this happen: Kani can verify the equivalence of the two versions. Note that, for the loop version, after each iteration max(u,v) decreases at least by 1 and u, v are u8, so the maximum number of iterations (unwinding) should be 256. It is similar for the two arguments of the recursive version.
Instead, this happened: The recursive version seems to be unwinded forever.
The text was updated successfully, but these errors were encountered: