Skip to content

Commit dea03c0

Browse files
Fix the bug of using multiple hidden variables for the prev of the same Expr (#4150)
This PR fixes the bug of using multiple hidden variables for the prev of the same Expr. Resolves #4149 By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.
1 parent f3ba917 commit dea03c0

File tree

3 files changed

+43
-3
lines changed

3 files changed

+43
-3
lines changed

library/kani_macros/src/sysroot/loop_contracts/mod.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,15 @@ impl VisitMut for CallReplacer {
136136
if let Expr::Call(call) = expr {
137137
if let Expr::Path(expr_path) = &*call.func {
138138
if self.should_replace(expr_path) {
139-
let new_var = self.generate_var_name();
140-
self.replacements.push((expr.clone(), new_var.clone()));
141-
*expr = syn::parse_quote!(#new_var);
139+
let replace_var =
140+
self.replacements.iter().find(|(e, _)| e == expr).map(|(_, v)| v);
141+
if let Some(var) = replace_var {
142+
*expr = syn::parse_quote!(#var);
143+
} else {
144+
let new_var = self.generate_var_name();
145+
self.replacements.push((expr.clone(), new_var.clone()));
146+
*expr = syn::parse_quote!(#new_var);
147+
};
142148
}
143149
}
144150
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
func::{closure#3}::{closure#0}::{closure#1}.assertion.1\
2+
- Status: SUCCESS\
3+
- Description: "attempt to add with overflow"
4+
5+
func.loop_invariant_step.1\
6+
- Status: SUCCESS\
7+
- Description: "Check invariant after step for loop func.0"
8+
9+
VERIFICATION:- SUCCESSFUL
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
// kani-flags: -Z loop-contracts -Z function-contracts
5+
6+
#![feature(proc_macro_hygiene)]
7+
#![feature(stmt_expr_attributes)]
8+
9+
#[kani::requires(x < 10)]
10+
fn func(x: usize) -> Option<usize> {
11+
let mut i: usize = 0;
12+
let mut r: usize = x;
13+
let N: usize = 7;
14+
#[kani::loop_invariant((i <= N && i >=0) && (on_entry(i) == 0 && prev(i) < 7 && prev(i) + 1 == i ) ) ]
15+
while i < N {
16+
i = i + 1;
17+
}
18+
if r + i >= x + N { Some(r) } else { None }
19+
}
20+
21+
#[kani::proof]
22+
fn harness() {
23+
let a = kani::any_where(|x: &usize| *x < 10);
24+
kani::assert(func(a).is_some(), "func(a) is some");
25+
}

0 commit comments

Comments
 (0)