Proving
Contracts describe what is true if a function returns. requires is a caller
obligation; ensures binds result. Opaque types may declare invariant.
spec fn and lemma fn are erased helpers. decreases proves Gale recursion
terminates. gale verify (or mix gale.verify) discharges these claims.
Compilation does not. Proofs do not mean a process is alive or a message was
delivered.
mod proving
pub fn increment(x: Integer) -> Integerrequires { x >= 0 }ensures { result == x + 1 }{ x + 1}
pub opaque type State = %{reserved: Integer, capacity: Integer}invariant(state) { state.reserved >= 0 and state.reserved <= state.capacity}
pub fn new(capacity: Integer) -> Result<State, :invalid> { if capacity >= 0 { Ok(%{reserved: 0, capacity: capacity}) } else { Error(:invalid) }}
pub fn available(state: State) -> Integerensures { result >= 0 }{ state.capacity - state.reserved}
pub fn zero(x: Integer) -> Integerrequires { x >= 0 }ensures { result == 0 }decreases { x }{ if x == 0 { 0 } else { zero(x - 1) }}
pub spec fn nonnegative(value: Integer) -> Boolean { value >= 0}
pub lemma fn successor(value: Integer) -> :okrequires { nonnegative(value) }ensures { nonnegative(value + 1) }{ :ok}
pub fn step(value: Integer) -> Integerrequires { nonnegative(value) }ensures { nonnegative(result) }{ proof { successor(value) } value + 1}requires is an obligation for callers and an assumption while checking the
body. ensures is an obligation on every normal return. result has the
declared return type. A false contract still typechecks; mix compile is not a
proof. Opaque construction and updates must establish the invariant.
spec fn and lemma fn are erased. Ordinary code cannot call them. A proof
block can use a lemma, then continues with a runtime expression. decreases
asks for a termination proof of Gale recursion. Server loops and GenServer
callbacks stay partial: if they return, their contracts hold.
Extern requires/ensures are trusted as written. Callers prove preconditions,
inhabit the declared return type, and assume postconditions. Uncontracted
foreign calls are not specification evidence:
extern "System.unique_integer" fresh() -> Integer
pub fn client() -> Integerensures { fresh() >= 0 }{ 0}gale check / mix gale.check typecheck annotations without solvers.
gale verify / mix gale.verify prove them with Why3 and Z3. Successful units
are reused from .gale/proofs. Proofs cover Gale code that returns normally.
They do not imply process survival or message delivery.