You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: hermes/llms-full.txt
+33-30Lines changed: 33 additions & 30 deletions
Original file line number
Diff line number
Diff line change
@@ -267,7 +267,7 @@ Hermes specifications are written directly in your Rust source code using specia
267
267
268
268
## 1. Annotation Chains
269
269
270
-
To attach a specification to a function, struct, or trait, write a `///` doc-comment block immediately preceding the definition.
270
+
To attach a specification to a function, struct, or trait, write a `///` doc-comment block immediately preceding the definition.
271
271
272
272
The block must begin with the `hermes` language string.
273
273
```rust
@@ -298,15 +298,15 @@ In addition to attaching specs directly to items, you can define a standalone bl
298
298
299
299
Hermes uses a strict, indentation-sensitive parser (similar to Python or YAML). **Whitespace is semantically significant.**
300
300
301
-
The rule is simple: **Any line that is indented further than the leading clause belongs to that clause.**
301
+
The rule is simple: **Any line that is indented further than the leading clause belongs to that clause.**
302
302
If you break an expression across multiple lines, every continuation line *must* be indented deeper than the line that started it.
303
303
304
304
**Valid:**
305
305
```rust
306
306
/// ```hermes
307
307
/// requires:
308
308
/// let x = 5
309
-
/// let y =
309
+
/// let y =
310
310
/// x + 2
311
311
/// ```
312
312
```
@@ -316,7 +316,7 @@ If you break an expression across multiple lines, every continuation line *must*
316
316
/// ```hermes
317
317
/// requires:
318
318
/// let x = 5
319
-
/// let y =
319
+
/// let y =
320
320
/// x + 2 <-- ERROR: Not indented deeper than `let y =`
321
321
/// ```
322
322
```
@@ -339,7 +339,7 @@ However, Hermes explicitly disables standard implicits in favor of **Strict Impl
339
339
340
340
**Why is this required?**
341
341
Standard implicits (`{}`) instruct Lean to eagerly guess and synthesize the typeclass immediately when the function is evaluated. For complex spatial traits (like `HasStaticLayout`), this eager synthesis often panics the solver before the proof even begins.
342
-
Strict implicits (`{{ }}`) politely instruct Lean to *delay* synthesis until the exact moment the trait is actively applied to a concrete value.
342
+
Strict implicits (`{{ }}`) politely instruct Lean to *delay* synthesis until the exact moment the trait is actively applied to a concrete value.
343
343
344
344
If you are refactoring a Hermes spec, do not replace `{{_sz: Sized Self}}` with `{_sz: Sized Self}`. You will likely break downstream proofs invisibly.
345
345
@@ -358,9 +358,9 @@ If you simply write an expression, you are defining an anonymous bound.
358
358
/// x > 0
359
359
/// ```
360
360
```
361
-
This requires that `x > 0`. Internally, Hermes names this bound `h_unnamed`.
361
+
This requires that `x > 0`. Internally, Hermes names this bound `h_anon`.
362
362
363
-
**The Singleton Limit:** Because Hermes collapses anonymous bounds into `h_unnamed`, **you may only have one anonymous bound per clause.** If you have multiple requirements, you must name them.
363
+
**The Singleton Limit:** Because Hermes collapses anonymous bounds into `h_anon`, **you may only have one anonymous bound per clause.** If you have multiple requirements, you must name them.
364
364
365
365
### Named Bounds
366
366
If multiple `requires` or `ensures` bounds are required, they must be named:
@@ -373,7 +373,7 @@ If multiple `requires` or `ensures` bounds are required, they must be named:
373
373
```
374
374
375
375
Naming your bounds is critical for two reasons:
376
-
1. It bypasses the `h_unnamed` singleton limit.
376
+
1. It bypasses the `h_anon` singleton limit.
377
377
2. It allows you to explicitly reference the proven hypothesis (like `h_x_positive`) in downstream proofs or custom lemmas. Any name you provide here becomes an active variable in the local Lean context during verification.
378
378
379
379
## 5. Axioms and FFI
@@ -396,7 +396,10 @@ In addition to function-level pre- and post-conditions, Hermes allows you to def
396
396
397
397
### `isValid`
398
398
399
-
`isValid` defines a structural invariant for a type.
399
+
> [!WARNING]
400
+
> `isValid` annotations are currently unsound. To use them, you must provide the `--unsound-allow-is-valid` flag to Hermes.
401
+
402
+
`isValid` defines a structural invariant for a type.
400
403
401
404
```rust
402
405
/// ```hermes
@@ -421,7 +424,7 @@ Under the hood, this implements the `Hermes.IsValid` typeclass for that struct.
421
424
pub unsafe trait Unaligned: Sized {}
422
425
```
423
426
424
-
Implementers of the `unsafe trait` must provide a proof of `isSafe`.
427
+
Implementers of the `unsafe trait` must provide a proof of `isSafe`.
425
428
426
429
**Crucially**, generic functions bounding on the trait (e.g., `fn foo<T: Unaligned>()`) **do not** automatically receive this mathematical assumption in their preconditions, because the trait bound alone does not prove the invariant holds in a generic context. You must explicitly request the `isSafe` property in your `requires` block (see Module 6 for how to consume and apply trait bounds).
427
430
@@ -483,7 +486,7 @@ Bounds are namespaced to either pre-conditions or post-conditions. An anonymous
Hermes automatically defines or injects the following structural names.
512
515
513
-
**`h_unnamed`**: The singleton name assigned to an anonymous `requires` or `ensures` block. These are namespaced to either pre-conditions or post-conditions, so they don't conflict.
516
+
**`h_anon`**: The singleton name assigned to an anonymous `requires` or `ensures` block. These are namespaced to either pre-conditions or post-conditions, so they don't conflict.
514
517
515
518
````rust
516
519
/// ```hermes
517
-
/// requires: x > 0 -- Named `h_unnamed`
518
-
/// ensures: ret = x + 1 -- Named `h_unnamed`
519
-
/// proof: -- Proves `h_unnamed`
520
+
/// requires: x > 0 -- Named `h_anon`
521
+
/// ensures: ret = x + 1 -- Named `h_anon`
522
+
/// proof: -- Proves `h_anon`
520
523
/// ...
521
524
/// ```
522
525
````
@@ -558,7 +561,7 @@ fn foo() -> MyType {}
558
561
/// proof (h_progress): -- Prove execution doesn't fail (e.g. divide by zero) or loop forever
559
562
/// ...
560
563
/// ```
561
-
fn safe_div(x: u32, y: u32) -> u32 {}
564
+
fn safe_div(x: u32, y: u32) -> u32 {}
562
565
````
563
566
564
567
**`h_returns`**: The hypothesis binding the successful evaluation of the function to the implicitly-available values `ret`, `arg'`, etc.
@@ -742,24 +745,24 @@ Writing a Lean proof is not like other forms of software engineering. A Lean pro
742
745
The following is a workflow for solving [problem]. It is recursive – you will use this workflow to solve sub-problems as well.
743
746
744
747
1. Make sure you understand your goal, context, and constraints for [problem] *completely* and *precisely*.
745
-
a. Spend as much time as you need *thinking* in order to come to this understanding.
746
-
b. If there is any ambiguity whatsoever, ask for clarification.
747
-
c. Repeat the process of clarification-asking and thinking until you have a *complete* and *precise* understanding of your goal, context, and constraints.
748
-
d. Record this in as much details as you can in comments the file you are editing.
748
+
1. Spend as much time as you need *thinking* in order to come to this understanding.
749
+
2. If there is any ambiguity whatsoever, ask for clarification.
750
+
3. Repeat the process of clarification-asking and thinking until you have a *complete* and *precise* understanding of your goal, context, and constraints.
751
+
4. Record this in as much details as you can in comments the file you are editing.
749
752
2. Once you understand the goal, context, and constraints for [problem], brainstorm a *complete* solution. Your solution must be *complete*, as the act of thinking through details may make you realize that you need to adjust your high-level plan.
750
-
a. Spend as much time as it takes to think through your solution *completely* until you are confident that *every detail* is correct.
751
-
b. Record this in as much details as you can in comments the file you are editing.
753
+
1. Spend as much time as it takes to think through your solution *completely* until you are confident that *every detail* is correct.
754
+
2. Record this in as much details as you can in comments the file you are editing.
752
755
3. You are now ready to start writing code.
753
-
a. Start with the specification (`requires` and `ensures` clauses).
754
-
b. Get these working with the `verify` subcommand and the `--allow-sorry` flag, omitting any proofs.
755
-
c. Iterate until everything verifies, implying that your specification is internally consistent. This does not necessarily mean that it's the *right* specification, only that Hermes understands it.
756
-
d. Run the `expand` subcommand to see what Lean is generated, and make sure it looks like what you expect. This will help you when you start writing proofs.
756
+
1. Start with the specification (`requires` and `ensures` clauses).
757
+
2. Get these working with the `verify` subcommand and the `--allow-sorry` flag, omitting any proofs.
758
+
3. Iterate until everything verifies, implying that your specification is internally consistent. This does not necessarily mean that it's the *right* specification, only that Hermes understands it.
759
+
4. Run the `expand` subcommand to see what Lean is generated, and make sure it looks like what you expect. This will help you when you start writing proofs.
757
760
4. Move on to the proof.
758
-
a. First, break the proof down into lemmas. Spend as much time as you need thinking through the lemmas and how they fit together to prove the main proof.
759
-
b. Write the *definitions* of each lemma, but do *not* prove them – leave their proofs as `sorry` for now.
761
+
1. First, break the proof down into lemmas. Spend as much time as you need thinking through the lemmas and how they fit together to prove the main proof.
762
+
2. Write the *definitions* of each lemma, but do *not* prove them – leave their proofs as `sorry` for now.
760
763
5. Write the top-level proof, using the lemmas you defined in the previous step.
761
-
a. Iterate until this proof verifies, using the `--allow-sorry` flag.
762
-
b. If you get stuck *at all*, consider whether you need to re-visit a previous step or "pop up" one level of abstraction to reconsider your broader plan.
764
+
1. Iterate until this proof verifies, using the `--allow-sorry` flag.
765
+
2. If you get stuck *at all*, consider whether you need to re-visit a previous step or "pop up" one level of abstraction to reconsider your broader plan.
763
766
6. Once the top-level proof verifies, you can start proving the lemmas one by one. For each lemma, you will use *this entire workflow*, but applied to [sub-problem] instead of the top-level [problem].
764
767
765
768
Overall, your workflow will look like a recursive application of this entire workflow. Always be prepared to "pop up" one level of abstraction to reconsider your broader plan.
0 commit comments