Skip to content

Commit

Permalink
support while loop with continue but no break, fixes #421
Browse files Browse the repository at this point in the history
  • Loading branch information
tjhance committed Dec 21, 2024
1 parent f47583e commit 09958f1
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 1 deletion.
62 changes: 62 additions & 0 deletions source/rust_verify_test/tests/loops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1452,3 +1452,65 @@ test_verify_one_file! {
}
} => Ok(())
}

test_verify_one_file! {
#[test] loop_continue_no_break verus_code! {
fn test() {
let mut i = 0;
while i < 5
invariant i <= 5
{
continue;
}
assert(i == 5);
}

fn test_fail_beginning() {
let mut x = 0;
let mut i = 7;
while i < 5
invariant x == 1 // FAILS
{
x = 1;
continue;
}
}

fn test_fail_at_continue() {
let mut x = 2;
let mut i = 7;
while i < 5
invariant x == 2
{
x = 1;
continue; // FAILS
}
}

fn test_fail_at_end_after_continue(b: bool) {
let mut x = 2;
let mut i = 7;
while i < 5
invariant x == 2 // FAILS
{
if b {
continue;
}
x = 1;
}
}

fn test_fail_at_end_after_continue_except_break(b: bool) {
let mut x = 2;
let mut i = 7;
loop
invariant_except_break x == 2 // FAILS
{
if b {
continue;
}
x = 1;
}
}
} => Err(err) => assert_fails(err, 4)
}
53 changes: 53 additions & 0 deletions source/rust_verify_test/tests/loops_no_spinoff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1362,3 +1362,56 @@ test_verify_one_file! {
}
} => Ok(())
}

test_verify_one_file! {
#[test] loop_continue_no_break_spinoff verus_code! {
fn test() {
let mut i = 0;
#[verifier::loop_isolation(false)]
while i < 5
invariant i <= 5
{
continue;
}
assert(i == 5);
}

fn test_fail_beginning() {
let mut x = 0;
let mut i = 0;
#[verifier::loop_isolation(false)]
while i < 5
invariant x == 1 // FAILS
{
x = 1;
continue;
}
}

fn test_fail_at_continue() {
let mut x = 2;
let mut i = 0;
#[verifier::loop_isolation(false)]
while i < 5
invariant x == 2
{
x = 1;
continue; // FAILS
}
}

fn test_fail_at_end_after_continue(b: bool) {
let mut x = 2;
let mut i = 0;
#[verifier::loop_isolation(false)]
while i < 5
invariant x == 2 // FAILS
{
if b {
continue;
}
x = 1;
}
}
} => Err(err) => assert_fails(err, 3)
}
2 changes: 1 addition & 1 deletion source/vir/src/sst_to_air.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1967,7 +1967,7 @@ fn stm_to_stmts(ctx: &Ctx, state: &mut State, stm: &Stm) -> Result<Vec<Stmt>, Vi
let is_air_break = *is_break && !loop_info.loop_isolation;
let mut stmts: Vec<Stmt> = Vec::new();
if !ctx.checking_spec_preconditions() && !is_air_break {
assert!(!loop_info.some_cond); // AST-to-SST conversion must eliminate the cond
assert!(!is_break || !loop_info.some_cond); // AST-to-SST conversion must eliminate the cond
if loop_info.is_for_loop && !*is_break {
// At the very least, the syntax macro will need to advance the ghost iterator
// at each continue.
Expand Down

0 comments on commit 09958f1

Please sign in to comment.