feat: intrinsic verification syntax for do-notation loops and def contracts#14389
feat: intrinsic verification syntax for do-notation loops and def contracts#14389sgraf812 wants to merge 1 commit into
Conversation
ae7fb19 to
2adc4e1
Compare
|
Mathlib CI status (docs):
|
|
Reference manual CI status:
|
fa3413e to
2e74ff6
Compare
261936f to
8249948
Compare
|
This is a fantastic feature. I’m looking forward to its release. |
aeff689 to
52530f0
Compare
|
!bench |
|
Benchmark results for 99e8d1c against 749f580 are in. There are significant results. @sgraf812
No significant changes detected. |
f8e503e to
a3f9058
Compare
|
!bench |
|
Benchmark results for a3f9058 against 749f580 are in. There are significant results. @sgraf812
Large changes (1🟥)
Small changes (2✅, 18🟥)
|
|
!bench |
|
Benchmark results for 243b273 against 749f580 are in. There are significant results. @sgraf812
Large changes (1🟥)
Small changes (21🟥)
|
|
!bench |
|
Benchmark results for 8b30968 against 749f580 are in. There are significant results. @sgraf812
Medium changes (1🟥)
Small changes (151🟥)
|
…tracts This PR adds intrinsic verification syntax for `Std.Internal.Do` do-notation: loop invariants and function contracts that `vcgen` discharges automatically. A `for x in xs invariant cur => I do …` loop annotates its invariant onto the loop combinator, elaborated in the loop body's scope so mutable variables and outer-loop variables resolve by name; nested loops are supported. A `def` may carry `require P` and `ensures b => Q` clauses on its signature, expanding to the plain definition plus an `@[spec]`-tagged specification theorem `f.spec : ⦃P⦄ f args ⦃fun b => Q⦄` proved by `vcgen [f] with finish`.
8b30968 to
f51437b
Compare
|
!bench |
|
Benchmarking f51437b against 7fc3135 (preliminary results). React with 👀 to be notified when the results are in. The command author is always notified. |
|
Benchmark results for f51437b against 7fc3135 are in. There are significant results. @sgraf812
New metrics (3✅, 2🟥)
Medium changes (1🟥)
Small changes (65🟥)
|
This PR adds intrinsic verification syntax for
Std.Internal.Dodo-notation: loop invariants and function contracts thatvcgendischarges automatically.A
for x in xs invariant cur => I do …loop annotates its invariant onto the loop combinator, elaborated in the loop body's scope so mutable variables and outer-loop variables resolve by name; nested loops are supported. Adefmay carryrequire Pandensures b => Qclauses on its signature, expanding to the plain definition plus an@[spec]-tagged specification theoremf.spec : ⦃P⦄ f args ⦃fun b => Q⦄proved byvcgen [f] with finish. The test examplefindSmallestis then fully automatic with zero manual proof.invariant,require, andensuresremain usable as ordinary identifiers; a bare occurrence only ends the preceding term in the position where the clause is expected. The contract expander is a builtin macro, so contracts work when onlyStd.Tactic.Dois imported. Scope is the MVP:forloops overListandStd.Legacy.Range;while,signals, and residual-VC discharge are not included.Performance
The contract clauses are parsed as an alternative tried only after the ordinary
defvalue parser fails, so a contract-freedefparses exactly the previous grammar and its syntax tree is unchanged; metaprograms matchingdefsyntax compile the same matchers as before. The remaining instruction regressions are small and intrinsic to adding syntax to the compiler: extending the built-indefanddogrammar enlarges the parser tables that every Lean process initializes at startup, a fixed cost of a few million instructions per invocation that recurs across all module builds and surfaces as a larger percentage only on the smallest modules, and the type in adefsignature is parsed withrequire/ensuresexcluded as identifiers, which reduces parser cache sharing for signatures by about +0.4% on the dedicated parser benchmark.