Skip to main content

__verus_proof_idempotent_fold__

Macro __verus_proof_idempotent_fold__ 

Source
macro_rules! __verus_proof_idempotent_fold__ {
    (
        acc = $accty:ty, item = $itemty:ty
        $(, captures = |$($cap:ident : $capty:ty),* $(,)?|)?
        $(, proof = |$pstate:ident, $px:ident| { $($proof_body:tt)* })?
        , __target = { $(move)? |$tacc:ident $(: $taccty:ty)?, $titem:ident $(: $titemty:ty)?| $target_body:expr }
        , __captures = [$($fv:ident),* $(,)?] $(,)?
    ) => { ... };
    (
        $($rest:tt)*
    ) => { ... };
}
Expand description

Fulfills an idempotent = ... proof parameter for a fold closure (shape |acc, item| with acc: &mut A) with a Verus-checked proof of idempotence.

Use verus_proof_idempotent_reduce! for reduce, whose accumulator is seeded with the first element, which needs an additional obligation.

Users never write the proof obligation (so they cannot get it wrong): this macro receives the quoted closure itself from q! (as a trailing __target = { ... } argument) and generates a Verus function that symbolically executes the actual closure body on an item x once, and on x twice in a row, starting from equal accumulators, and asserts that the final accumulators are equal. Verifying this obligation also proves the closure body panic-free (e.g. no arithmetic overflow). Users only declare the accumulator and item types:

ⓘ
stream.fold(
    q!(|| 0u32),
    q!(
        |acc, x| { if x > *acc { *acc = x; } },
        idempotent = verus_proof_idempotent_fold!(acc = u32, item = u32)
    ),
);

Read-only captures are declared in a captures = |...| clause, exactly as for verus_proof_commutative_fold!; the macro checks at compile time that every capture is declared.

An optional proof = |state, x| { ... } clause supplies a proof script to help the SMT solver, with ghost bindings for the initial accumulator and the item (e.g. proof = |s, x| { assert(((s | x) | x) == (s | x)) by (bit_vector); }). The script is checked by Verus and cannot weaken the obligation.

The proof is gated on cfg(verus_keep_ghost), so it only exists when the crate is compiled by the Verus driver (cargo verus verify). Under normal compilation the macro just produces a VerusIdempotentProof marker.