ghost_in_runtime: a ghost value used by the running program
A ghost parameter (ghost s : T), a ghost let and a ghost fn exist only for proofs: the
compiler removes them before the program runs. So the program itself may not use one. A ghost
value may appear only where nothing runs:
- in a refinement, such as a parameter’s or the result’s;
- in another
ghost let, or as the argument of a ghost parameter; - as a lemma’s argument, or in a proof hint (
assert … by,calc); - in a
ghost fn’s body.
Returning it, branching or matching on it, capturing it in a closure, passing it to an
ordinary parameter, or calling a ghost fn from ordinary code is this error.
A program that triggers it
mod Main do
fn clamp(x : Int, ghost limit : Int) : Int do
if x > limit do limit else x end
end
end
The fix
If the program needs the value, it is not ghost: make it an ordinary parameter.
mod Main do
fn clamp(x : Int, limit : Int) : Int do
if x > limit do limit else x end
end
end
If only the proof needs it, keep it ghost and use it in the contract instead:
mod Main do
fn below(ghost limit : Int, x : {Int | _ < limit}) : {Int | _ < limit} do
x
end
end
Why the rule exists
Erasing ghost code must not change what the program does. If a branch, a result or a closure could depend on a ghost value, removing it would leave the program reading something that no longer exists, or would change its behaviour. Keeping ghost values out of every runtime position makes erasure safe by construction.
See also: the lemmas guide, ghost_misuse.