> SPARK has no escape hatches
It does, you can declare a procedure in SPARK but implement it in regular Ada. Ada is SPARK's escape hatch.
This is just as visible in source code as unsafe is in Rust, a procedure body will have SPARK_Mode => Off.
> SPARK has no escape hatches
It does, you can declare a procedure in SPARK but implement it in regular Ada. Ada is SPARK's escape hatch.
This is just as visible in source code as unsafe is in Rust, a procedure body will have SPARK_Mode => Off.
Yes, SPARK provides an explicit escape hatch, but it is meaningfully different from Rust's `unsafe`.
In SPARK: you keep the spec in the verifiable world (a SPARK-visible subprogram declaration) and place the implementation outside the proof boundary (for example in a body or unit compiled with `pragma SPARK_Mode(Off)`). The body is visible in source but intentionally opaque to the prover; callers are still proved against the spec and must rely on that contract.
In Rust: `unsafe` is a lexical, language-level scope or function attribute that disables certain compiler/borrow checks for the code inside the block or function. The unchecked code remains inline and visible; the language/borrow-checker no longer enforces some invariants there, so responsibility shifts to the programmer at the lexical site.
Practical differences reviewers should understand:
- Granularity: `unsafe` is lexical (blocks/functions); SPARK's hatch is modular/procedural (spec vs body).
- Visibility: Rust's unchecked code is written inline and annotated with `unsafe`; SPARK's unchecked implementation is placed outside the prover but the spec remains visible and provable.
- Enforcement model: Rust's safety holes are enforced/annotated by the compiler's type/borrow rules (caller and callee responsibilities are explicit at the site). SPARK enforces sound proofs on the interface; the off-proof body must be shown (by review/tests/docs) to meet the proven contract.
- Best practice: keep off-proof bodies tiny, give strong pre/postconditions on the SPARK spec, minimize the exposed surface, and rigorously review and test the non-SPARK implementation.
TL;DR: `unsafe` = "this code block bypasses language checks"; SPARK's escape hatch = "this implementation is deliberately outside the prover, but the interface is still what we formally prove against."