Skip to content

Commit 68415ff

Browse files
authored
Fix loop contracts transformation when loops in branching (#3640)
In loop contracts transformation, we want to visit non-loop blocks before visiting loop blocks. So we pop `loop_queue` only when `queue` is empty. We should use `or_else` instead of `or` which always pop the front of `loop_queue`. 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 2402892 commit 68415ff

File tree

2 files changed

+12
-8
lines changed

2 files changed

+12
-8
lines changed

kani-compiler/src/kani_middle/transform/loop_contracts.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ impl TransformPass for LoopContractPass {
114114
let mut loop_queue: VecDeque<BasicBlockIdx> = VecDeque::new();
115115
queue.push_back(0);
116116

117-
while let Some(bb_idx) = queue.pop_front().or(loop_queue.pop_front()) {
117+
while let Some(bb_idx) = queue.pop_front().or_else(|| loop_queue.pop_front()) {
118118
visited.insert(bb_idx);
119119

120120
let terminator = new_body.blocks()[bb_idx].terminator.clone();
@@ -126,9 +126,11 @@ impl TransformPass for LoopContractPass {
126126
// the visiting queue.
127127
for to_visit in terminator.successors() {
128128
if !visited.contains(&to_visit) {
129-
let target_queue =
130-
if is_loop_head { &mut loop_queue } else { &mut queue };
131-
target_queue.push_back(to_visit);
129+
if is_loop_head {
130+
loop_queue.push_back(to_visit);
131+
} else {
132+
queue.push_back(to_visit)
133+
};
132134
}
133135
}
134136
}

tests/expected/loop-contract/multiple_loops.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111
fn multiple_loops() {
1212
let mut x: u8 = kani::any_where(|i| *i >= 10);
1313

14-
#[kani::loop_invariant(x >= 5)]
15-
while x > 5 {
16-
x = x - 1;
14+
if x != 20 {
15+
#[kani::loop_invariant(x >= 5)]
16+
while x > 5 {
17+
x = x - 1;
18+
}
1719
}
1820

19-
assert!(x == 5);
21+
assert!(x == 5 || x == 20);
2022

2123
#[kani::loop_invariant(x >= 2)]
2224
while x > 2 {

0 commit comments

Comments
 (0)