Skip to content
Kavachकवच

Contracts: ensure

● Intermediate3 min

ensure states what the function promises; result is the value it gives back.

type Account {
    owner: String
    balance: Decimal
}

fn withdraw(account: Account, amount: Decimal) -> Account
    require amount > 0
    require amount <= account.balance
    ensure result.balance == account.balance - amount
{
    account with { balance: account.balance - amount }
}

fn main() {
    const after = withdraw(Account(owner: "Asha", balance: 500), 120)
    print(after.balance)
}

The program ran and printed:

kavach run ensure.kav

380
ensure.kav: Kavach code, then what running it prints

account.balance in the ensure is the balance before the call: parameters are values and never change, so no special "old value" syntax is needed. An ensure is checked only when the function succeeds.

Found before it runs

When the function gives back a value the compiler knows, and an ensure that compares result with a number is false for it, that is a compile error. This holds for the end of the function, a branch at its end, or a return, even in a branch that may not run: whenever it runs, it panics.

fn clamp_low(x: Int) -> Int
    ensure result >= 0
{
    if x < 0 {
        return -1
    }
    x
}

fn main() {
    print(clamp_low(5))
}

The compiler refused the program:

kavach run ensure-known.kav

error: this always breaks `ensure result >= 0` of `clamp_low`: `result` is -1 (spec 7.7)
ensure-known.kav: Kavach code, then what running it prints