We want to be able to guarantee that "cargo hermes verify succeeded" implies "this program is sound". With enough Hermes features, this should be bulletproof via the following reasoning:
Other considerations:
- How do we ensure that all
unsafe and unsafe impl blocks are annotated? We could either rely on the Clippy lint or have Hermes do its own analysis and reject undocumented unsafe blocks
- How do we ensure that all safety comments/Hermes annotations behave as expected? For example, if Hermes just ensures that a block has a Hermes annotation or a safety comment, what if the user intended to write a Hermes annotation, but typo'd it, and so we treat it as an opaque safety comment and don't validate its contents? Maybe, instead, we could require users to opt out? E.g., the default behavior of Hermes is to require every
unsafe block to be annotated with a Hermes annotation, and one of the valid annotations is "unchecked prose safety proof" or something like that. Could opt-out with cargo hermes verify --allow-partial or something like that.
Another thing to consider: We need to ensure that a function or unsafe block which calls an unsafe function without a Hermes annotation must itself either not have a Hermes annotation or have an unsafe(axiom) annotation. The reason is that an unsafe function without a Hermes annotation will appear to Lean to have no safety preconditions. For example, you could do:
unsafe fn unreachable_unchecked() {
unsafe { std::hint::unreachable_unchecked() }
}
/// ```hermes, spec
/// ensures ret = t
/// proof
/// ...
/// ```
fn identity<T>(t: T) -> T {
unsafe { unreachable_unchecked() }
t
}
identity is actually unsound because it calls unreachable_unchecked, but since unreachable_unchecked doesn't have a Hermes annotation, the lowered Lean for identity won't realize that unreachable_unchecked has any preconditions, and so it will accept a proof of identity's spec as valid.
We want to be able to guarantee that "
cargo hermes verifysucceeded" implies "this program is sound". With enough Hermes features, this should be bulletproof via the following reasoning:unsafeblock (already guaranteed by Rust)unsafe implblock (already guaranteed by Rust)unsafeandunsafe implblocks must carry a safety comment (can be guaranteed by Hermes, similar to the Clippy lint)unsafeblocks, we need a way to parse normal (non-doc) comments and to support comments which are anchored on blocks instead of on function definitions, trait definitions, or trait impl blocksunsafe implblocks must have a proof of correctness which depends only on left-hand-side trait boundsunsafeblocks must have a proof of correctness which depends only on function preconditionsunsafefunctions – a function which needs to beunsafe(because it needs safety preconditions) cannot be marked assafebecause then the inline Hermes safety proof will fail to verifyensurespost-conditions must also prove that their pre-conditions (eitherrequiresforunsafefunctions or no preconditions for safe functions) imply their post-conditionsrequirespreconditions, as safe functions must assume that they can be called by any valid type-checked code with any argumentsisSafeinvariantsunsafefields" feature. We'll somehow need to reason about the total set of code which can mutate a field. We may need Hermes annotations to live on the containing module or something.Other considerations:
unsafeandunsafe implblocks are annotated? We could either rely on the Clippy lint or have Hermes do its own analysis and reject undocumentedunsafeblocksunsafeblock to be annotated with a Hermes annotation, and one of the valid annotations is "unchecked prose safety proof" or something like that. Could opt-out withcargo hermes verify --allow-partialor something like that.Another thing to consider: We need to ensure that a function or
unsafeblock which calls anunsafefunction without a Hermes annotation must itself either not have a Hermes annotation or have anunsafe(axiom)annotation. The reason is that anunsafefunction without a Hermes annotation will appear to Lean to have no safety preconditions. For example, you could do:identityis actually unsound because it callsunreachable_unchecked, but sinceunreachable_uncheckeddoesn't have a Hermes annotation, the lowered Lean foridentitywon't realize thatunreachable_uncheckedhas any preconditions, and so it will accept a proof ofidentity's spec as valid.