Skip to content

feat: redesign mvcgen' for a new meta theory #13978

Closed
volodeyka wants to merge 86 commits into
masterfrom
vova/mvcgen'
Closed

feat: redesign mvcgen' for a new meta theory #13978
volodeyka wants to merge 86 commits into
masterfrom
vova/mvcgen'

Conversation

@volodeyka

@volodeyka volodeyka commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

This PR rewrites the experimental mvcgen' tactic on top of a new meta theory from #12965.

Except new meta theory, the main technical difference from the current mvcgen' is that it, when solving pre ⊑ wp x post epost eagerly introduces all the state components. In other words, if for a monad m we are working with, the shape of the corresponding assertion language Pred is σ₁ → σ₂ → ⋯ → σₙ → l, then we will immediately introduce s₁ : σ₁, s₂ : σ₂, … , sₙ : σₙ yielding pre s₁ s₂ ⋯ sₙ ⊑ wp x post epost s₁ s₂ ⋯ sₙ. Most of the time, since we work with Pred type of σ₁ → σ₂ → ⋯ → σₙ → Prop shape, pre s₁ s₂ ⋯ sₙ would be of type Prop and we can introduce it into a local context. This prevents us from information loss and potentially enables more grind internalization (since more facts are introduced to a local context).

We also change how we specify the invariants for all kinds of loops, iterators, folds, maps and so on…
Before, if you had a loop throwing an exception inside, say,

def throwing_loop : ExceptT Nat (StateT Nat Id) Nat := do
  let mut x := 0
  let s ← get
  for i in [1:s] do { x := x + i; if x > 4 then throw 42 }
  set 1
  return x

when you call mvgen' you should have specified the invariant together with a condition on exception:

theorem throwing_loop_spec :
  ⦃fun s => ⌜s = 4⌝⦄
  throwing_loop
  ⦃post⟨fun _ _ => ⌜False⌝,
        fun e s => ⌜e = 42 ∧ s = 4⌝⟩⦄ := by
  mvcgen' [throwing_loop]
  case inv1 => exact post⟨fun (xs, r) s => ⌜r ≤ 4 ∧ s = 4 ∧ r + xs.suffix.sum > 4⌝, -- actual invarinat
                         fun e s => ⌜e = 42 ∧ s = 4⌝⟩  -- condition on exception

Now The condition on exception would be just assumed to be the one specified in the Triple globally:

theorem throwing_loop_spec :
  ⦃fun s => s = 4⦄
  throwing_loop
  ⦃fun _ _ => False;
  fun e s => e = 42 ∧ s = 4⦄ := by
  mvcgen' [throwing_loop]
  case inv1 => exact ⟨fun (xs, r) s => r ≤ 4 ∧ s = 4 ∧ r + xs.suffix.sum > 4⟩ -- only the invariant

This should make the invariant specification more straightforward.

Internally, the Internal/VCGen rule-construction layer is split into a RuleConstruct/ submodule by rule kind (Logic, Match, Simp, Spec), a new EPost module is added for exception-postcondition handling, and shared Types/Utils modules are introduced; the previous flat Context, Entails, Reduce, RuleConstruction, and Util modules are removed. The assumption discharger is threaded from the frontend config through the driver into the solver.

On the library side it reorganizes the Std.Internal.Do order/assertion metatheory into an Order/ namespace (Basic, Frame, Lemmas), renaming Std/Internal/Do/Frame.lean to Std/Internal/Do/Order/Frame.lean, and updates the Std.Internal.Do.Triple/WP specs that build on it.

This is the second of two steps that land vova/new-mvcgen onto master. The first step (#13954) updated the @[spec] builtin attribute and regenerated stage0, so this PR reuses master's stage0 and contains no generated C changes.

volodeyka added 30 commits June 9, 2026 10:31
….Elab.Tactic.Do.Options` for configuration. Update multiple tactics to conditionally dispatch based on the new option, replacing the legacy `new_proof_mode` references.
…ging spec theorems with pattern-based matching and migration support for the new `new_wp_monad` configuration.
…nstruction from specs, enhancing the handling of proof terms and verification conditions in the new `new_wp_monad` context.
…ruction

This commit introduces a new file `Logic.lean` containing definitions and theorems related to lattice logic operations, including the construction of backward rules for logical expressions. Key features include mappings of logic operators to their corresponding lemmas and the implementation of helper functions for equality lifting and distribution. Additionally, tests for various logical operations are included to ensure correctness and functionality.
This commit introduces a new file `Match.lean` that implements the `mkBackwardRuleForSplit` function, which creates reusable backward rules for splitting `ite`, `dite`, or matchers. The file includes a comprehensive test suite to validate the functionality of the backward rule construction, ensuring correct handling of various monadic setups and logical expressions.
This commit updates the `Intros.lean` file by refactoring the introduction procedures for handling variables and hypotheses in VCGen goals. The `IntroRules` structure has been removed in favor of directly using `VCGen.IntroRules`. New methods for goal simplification and variable introduction have been added, enhancing the handling of excess state arguments and improving the overall functionality of the Loom tactics.
This commit introduces a new file `Types.lean` within the Loom Tactic namespace, implementing the VCGen module. Key features include the definition of the `dischargeTactic` type for handling various discharge strategies, structures for caching backward rules and context management, and the VCGen monad for stateful computations. This addition enhances the Loom framework's capabilities for generating and managing verification conditions in proof tasks.
This commit introduces a new file `RuleCache.lean` that implements caching for various backward rule construction functions within the Loom Tactic namespace. Key features include cached versions of `tryMkBackwardRuleFromSpec`, `mkBackwardRuleForSplit`, and `mkBackwardRuleForLogic`, which enhance performance by storing previously computed rules based on specific cache keys. This addition improves the efficiency of verification condition generation and management in the Loom framework.
This commit introduces a new file `Solve.lean` that implements the main `solve` step for handling verification conditions in the Loom Tactic namespace. Key features include the classification of goals into various types, such as trivial, lattice, and EPost components, along with the core logic for decomposing goals into subgoals. This addition enhances the Loom framework's capability to manage complex verification conditions and improves the overall efficiency of the proof process.
This commit introduces two new files: `Driver.lean` and `Frontend.lean`, which implement the core functionality for the `lmvcgen` tactic in the Loom framework. The `Driver` module manages the worklist for verification condition generation, handling invariant subgoals, and emitting verification conditions. The `Frontend` module parses user input for the `lmvcgen` tactic, constructs the necessary context, and integrates with the VCGen process. These additions enhance the Loom framework's capabilities for managing complex proof tasks and improve user interaction with the verification condition generation process.
…tic file

This commit updates the `lakefile.lean` to enable precompilation of modules for the Loom package, enhancing build performance. Additionally, the obsolete `ShareExt.lean` file has been removed, streamlining the codebase and eliminating unused functionality related to the Loom Tactic namespace.
This commit updates various test files in the Loom framework to replace the obsolete `@[lspec]` attribute with the new `@[spec]` attribute for theorem specifications. Additionally, the `set_option new_wp_monad true` is added to several files to enable the new WP monad configuration. These changes enhance consistency across the test suite and align with recent updates in the Loom Tactic namespace.
This commit introduces the `WPInfo` structure in the Loom Tactic namespace, which encapsulates common metadata for goals related to weakest-precondition applications. The structure includes fields for the `wp` function head, core arguments, and extra arguments. Additionally, helper definitions for accessing specific components of `WPInfo` are provided, enhancing the framework's ability to manage and utilize weakest-precondition information in verification tasks.
This commit updates several functions in the Loom Tactic namespace to leverage the newly introduced `WPInfo` structure. The changes include modifying function signatures and internal logic to use `WPInfo` for managing arguments and types, enhancing code clarity and maintainability. Functions affected include `mkBackwardRuleForSplit`, `mkSimpBackwardProof`, and `tryMkBackwardRuleFromSpec`, among others. This refactor improves the handling of weakest-precondition applications and aligns with recent structural enhancements in the Loom framework.
…for program categorization. Refactor `classifyGoalKind` to `classifyGoal`, integrating `WPInfo` for improved handling of weakest-precondition applications. This update streamlines the classification process and enhances code clarity.
@volodeyka volodeyka requested review from TwoFX and sgraf812 as code owners June 9, 2026 05:48
@volodeyka volodeyka added the changelog-tactics User facing tactics label Jun 9, 2026
@volodeyka volodeyka changed the title feat: Reimplement mvcgen' based on new meta theory feat: reimplement mvcgen' based on new meta theory Jun 9, 2026
@volodeyka volodeyka changed the title feat: reimplement mvcgen' based on new meta theory feat: redesign mvcgen' for a new meta theory Jun 9, 2026
@volodeyka volodeyka marked this pull request as draft June 9, 2026 05:55
@github-actions github-actions Bot added the toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN label Jun 9, 2026
@mathlib-lean-pr-testing

mathlib-lean-pr-testing Bot commented Jun 9, 2026

Copy link
Copy Markdown

Mathlib CI status (docs):

  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase 6b63f7d1b6974968df366dd8746f6f8ce9b7f956 --onto 8391b966bc6078e6357d0916745f4ff226de1f61. You can force Mathlib CI using the force-mathlib-ci label. (2026-06-09 06:23:43)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase 659e8bb858995b0a1ada239c5b3819c8f8f2772f --onto a806b5c9771998bcd75a5920da160b6d14a39346. You can force Mathlib CI using the force-mathlib-ci label. (2026-06-09 15:09:51)

@leanprover-bot

leanprover-bot commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Reference manual CI status:

  • ❗ Reference manual CI will not be attempted unless your PR branches off the nightly-with-manual branch. Try git rebase 6b63f7d1b6974968df366dd8746f6f8ce9b7f956 --onto 803553a556fd82fa1060efb0c43eda542130cb16. You can force reference manual CI using the force-manual-ci label. (2026-06-09 06:23:45)
  • ❗ Reference manual CI will not be attempted unless your PR branches off the nightly-with-manual branch. Try git rebase 659e8bb858995b0a1ada239c5b3819c8f8f2772f --onto 803553a556fd82fa1060efb0c43eda542130cb16. You can force reference manual CI using the force-manual-ci label. (2026-06-09 15:09:53)

sgraf812 added a commit that referenced this pull request Jun 12, 2026
The solver lifts a pure precondition unconditionally when it sees one, as in #13978: an embedded `⌜φ⌝` before state-argument introduction, a bare proposition on the `Prop` lattice right after it. The lifted hypothesis is cached in `Scope.lastLiftedPre?`, and the targeted assumption step closes subsequent handoff VCs against it with a single defeq check, so no spec-rule sensitivity is needed; the rule construction returns to producing plain backward rules and the duplication guards before splits disappear.

Co-authored-by: volodeyka <vovaglad00@gmail.com>
@sgraf812 sgraf812 closed this Jun 16, 2026
jgoldfar pushed a commit to jgoldfar/lean4 that referenced this pull request Jun 16, 2026
…eanprover#14015)

This PR ports the experimental `mvcgen'` tactic to the new
`Std.Internal.Do` meta theory, where verification-condition generation
works on lattice entailments `pre ⊑ wp x post epost`. Two changes are
visible at the proof surface: `mvcgen'` now eagerly introduces all state
components as local hypotheses, so more facts reach `grind`; and loop
invariants no longer have to restate the exceptional postcondition.

Previously the invariant for a loop that can throw had to repeat the
exception condition alongside the actual invariant:
```lean
theorem throwing_loop_spec :
    ⦃fun s => ⌜s = 4⌝⦄
    throwing_loop
    ⦃post⟨fun _ _ => ⌜False⌝,
          fun e s => ⌜e = 42 ∧ s = 4⌝⟩⦄ := by
  mvcgen' [throwing_loop]
  case inv1 => exact post⟨fun (xs, r) s => ⌜r ≤ 4 ∧ s = 4 ∧ r + xs.suffix.sum > 4⌝,
                         fun e s => ⌜e = 42 ∧ s = 4⌝⟩
```
Now the exceptional postcondition is taken from the surrounding
`Triple`, so the invariant case carries only the invariant:
```lean
theorem throwing_loop_spec :
    ⦃fun s => s = 4⦄
    throwing_loop
    ⦃fun _ _ => False;
     fun e s => e = 42 ∧ s = 4⦄ := by
  mvcgen' [throwing_loop]
  case inv1 => exact ⟨fun (xs, r) s => r ≤ 4 ∧ s = 4 ∧ r + xs.suffix.sum > 4⟩
```

The spec lemmas in `Std.Internal.Do.Triple.SpecLemmas` are registered
with `@[spec]` and populate the new spec database, which also gains the
`whileM`/`Lean.Loop` specifications, `Invariant.withEarlyReturnNewDo`,
and pointwise entailment lemmas for state introduction.

The port replays Vladimir Gladshtein's leanprover#13978 onto master's file
structure.

The solver diverges from the legacy algorithm in three points.
Reflexivity runs on every entailment before the pure-precondition lifts,
closing the leaf VCs where a spec precondition meets an identical goal
precondition (`Q x ⊑ wp (pure x) Q E` ends in `Q x ⊑ Q x`) and
instantiating spec parameters that occur only in rule premises.
Reflexivity no longer assigns synthetic opaque metavariables, so
function-typed invariant holes are not silently solved away. Pure
preconditions are lifted into the local context as soon as they arise;
the lifted hypothesis is cached in `Scope.lastLiftedPre?`, and a
targeted assumption step closes the handoff VCs of subsequent spec
applications against it.

This is the second of two steps that land `vova/new-mvcgen` onto master.
The first step (leanprover#13954) updated the `@[spec]` builtin attribute and
regenerated `stage0`, so this PR reuses master's `stage0` and contains
no generated C changes. Invariant suggestion (`invariants?`) yields no
suggestions on the new surface; porting the suggestion analysis is
deferred until `mvcgen'` replaces the legacy `mvcgen`.

---------

Co-authored-by: volodeyka <vovaglad00@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog-tactics User facing tactics toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants