Skip to content

Loop contracts are not composable with function contracts #3910

Open
@carolynzech

Description

@carolynzech

I tried this code:

#![feature(stmt_expr_attributes)]
#![feature(proc_macro_hygiene)]

#[kani::requires(true)]
fn simple_loop_with_loop_contracts() {
    let mut x: u64 = kani::any_where(|i| *i >= 1);

    #[kani::loop_invariant(x >= 1)]
    while x > 1 {
        x = x - 1;
    }

    assert!(x == 1);
}


#[kani::proof_for_contract(simple_loop_with_loop_contracts)]
fn foo() {
    simple_loop_with_loop_contracts()
}

using the following command line invocation:

cargo kani -Z function-contracts -Z loop contracts

with Kani version: 0.59

I expected to see this happen: verification succeeds

Instead, this happened: the loop invariant is ignored, so the loop unwinds forever.

I find it confusing that we call it a "loop contract" and yet we can't use a "proof for contract" for it.

The same unwinding behavior happens if I change the harness to be a #[kani::proof]--it appears we can't prove invariants at all in the presence of other contracts.

Metadata

Metadata

Assignees

No one assigned

    Labels

    [C] BugThis is a bug. Something isn't working.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions