con un clic
fstarverifier
Verify F* and Pulse code with fstar.exe and interpret errors
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Menú
Verify F* and Pulse code with fstar.exe and interpret errors
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Basado en la clasificación ocupacional SOC
| name | fstarverifier |
| description | Verify F* and Pulse code with fstar.exe and interpret errors |
This skill is used when:
#lang-pulse) files# Verify a single file (stage3 fstar.exe includes Pulse support)
fstar.exe Module.fst
# With project include paths and caching
fstar.exe --cache_checked_modules --cache_dir _cache \
--already_cached Prims,FStar,Pulse.Nolib,Pulse.Lib,Pulse.Class,PulseCore \
--include path/to/spec --include path/to/impl \
Module.fst
# Verify interface first, then implementation (always in this order)
fstar.exe Module.fsti
fstar.exe Module.fst
| Flag | Purpose |
|---|---|
--query_stats | Show per-query timing and success/failure |
--split_queries always | Send each assertion as a separate Z3 query |
--log_queries | Write .smt2 files for Z3 query inspection |
--z3refresh | Restart Z3 between queries (detect flaky proofs) |
--print_full_names | Show fully qualified names (catch symbol confusion) |
--print_implicits | Show implicit arguments (debug unification) |
--detail_errors | More precise error locations, but can take much longer |
# Combined debugging
fstar.exe --query_stats --split_queries always --z3refresh Module.fst
#push-options "--z3rlimit 10" // SMT timeout (target ≤ 10)
#push-options "--fuel 1 --ifuel 1" // Recursion unfolding depth
#push-options "--z3rlimit 10 --fuel 0 --ifuel 0" // Tight: no unfolding
Cause: SMT cannot establish the postcondition from available facts.
Solutions:
assert statements to locate the gapSeq.equal / Set.equal for collection equality (not ==)FS.all_finite_set_facts_lemma() before FiniteSet reasoning--print_full_names)unfold needs a matching foldCause: Symbol not in scope.
Solutions:
open declarations and module X = ... aliases--print_full_names on a working referenceCause: Proof too complex for SMT within the time limit.
Solutions:
--fuel 0 --ifuel 0{:pattern ...} on quantifiers for controlled instantiation[@@"opaque_to_smt"] and reveal_opaque manuallyDo not just increase rlimit — find the root cause instead.
Cause: Type mismatch, often involving refinements.
Solutions:
(x <: refined_type)Cause: Cannot prove a refinement type's predicate.
Solutions:
assert establishing the predicate just before the expressionCause: Match expression doesn't cover all cases.
Solutions:
| _ -> ...--warn_error -321 only if completeness is verifiedCause: Calling a stateful (stt) function inside a ghost context.
How this happens:
with x y. _ are ghostif condition depends on ghost values, both branches become ghostSolutions:
// WRONG: ghost_seq is ghost from 'with'
let val = Seq.index ghost_seq idx;
let data = !some_ref; // Error: ghost context
// RIGHT: Read from the actual array
let val = arr.(idx); // Concrete
Cause: Trying to bind a concrete type from a ghost expression.
Solutions:
let x : erased (list entry) = ...assert (pure (Cons? ghost_list))Cause: Predicate arguments don't match the definition.
Solutions:
Cause: A pure (...) assertion in the slprop cannot be established.
Solutions:
assert (pure (...)) stepsEvery predicate manipulation must be balanced:
unfold (is_valid table spec);
// ... work with exposed resources ...
fold (is_valid table spec);
For range predicates, use get/put helpers:
get_at ptrs contents lo hi idx; // Extract element from range
// ... work with element ...
put_at ptrs contents lo hi idx; // Restore range
drop_ non-empty resources — this is a memory leakdrop_ (LL.is_list null_ptr []); // OK: empty list is null
// drop_ (LL.is_list ptr (hd::tl)); // WRONG: memory leak!
B.free: let b = B.alloc v; ... B.free barr |-> contents // Full permission: read and write
A.pts_to arr #p contents // Fractional: read-only (p is a fraction)
// MUST call before FiniteSet assertions
FS.all_finite_set_facts_lemma();
assert (FS.cardinality (FS.remove x s) == FS.cardinality s - 1);
assert (Seq.equal s1 s2); // NOT: s1 == s2
assert (Set.equal set1 set2);
assert (pure (SZ.v idx < len));
assert (pure (len <= SZ.v capacity));
assert (pure (SZ.fits (SZ.v capacity)));
assert (pure (SZ.fits (SZ.v idx + 1)));
let next = idx `SZ.add` 1sz;
my_arithmetic_lemma arg1 arg2; // Ghost: costs nothing at runtime
assert (pure (conclusion_of_lemma));
while (!i <^ len)
invariant exists* vi v_acc.
R.pts_to i vi **
R.pts_to acc v_acc **
A.pts_to arr #p s **
pure (SZ.v vi <= Seq.length s /\ v_acc == partial_result s (SZ.v vi))
{
// loop body
}
Do NOT use invariant b. exists* ... style.
.fsti interface first with full pre/post conditions.fsti.fst with admit() placeholders to validate structure--query_stats to find slow/cancelled queries--split_queries always to isolate which assertion failsassert statements to binary-search the failure point--z3refresh to detect order-dependent proofsadmit() or assume_ callsdrop_ of non-empty resources (Pulse)--query_stats shows no cancelled queriesFSTAR_HOME/ulib/ — F* standard library sourcesFSTAR_HOME/pulse/test/ — Pulse test cases and examplesFSTAR_HOME/pulse/lib/pulse/lib/ — Pulse library sourcesproofdebugging skill for systematic debugging workflowsUse the F* MCP server for interactive, incremental typechecking of F* and Pulse code
Extract verified F*/Pulse code to C via KaRaMeL (.krml intermediate representation)
Structure a new F*/Pulse verification project with Makefile and directory layout
Systematic workflows for debugging F*/Pulse verification failures
Debug F* queries sent to Z3, diagnosing proof instability and performance issues
Build F*, Pulse, and KaRaMeL from source (fstar2 branch) for use in a verification project