Skip to content

refactor: make the Std.Internal.Do loop invariant non-dependent - #14601

Merged
sgraf812 merged 6 commits into
masterfrom
sg/invariant-no-cursor
Jul 30, 2026
Merged

refactor: make the Std.Internal.Do loop invariant non-dependent#14601
sgraf812 merged 6 commits into
masterfrom
sg/invariant-no-cursor

Conversation

@sgraf812

@sgraf812 sgraf812 commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

This PR makes the loop invariant of Std.Internal.Do a plain function of the elements consumed so far and the elements remaining, rather than a cursor indexed by the list being iterated. The for … invariant clause binds two lists, invariant pref suff => …, and verification conditions mention them directly instead of { prefix := …, suffix := …, property := ⋯ }.prefix.

Invariant xs β Pred := List.Cursor xs → β → Pred becomes Invariant α β Pred := List α → List α → β → Pred. The relation pref ++ suff = xs moves out of the type and into the hypotheses of the verification conditions, where it already appears. Dropping the index removes the List.Cursor.cast transports and the property proofs from the specification lemmas, and frees the forInWithInvariant gadgets from naming a list at all: taking inv : Invariant α β Pred, they no longer need the ForIn.toList bridge lemmas or the [ForIn Id ρ α] argument those required. RepeatInvariant, used for repeatM, was already non-dependent.

Std.Do is unchanged except for deleting List.Cursor.cast, which now has no use in either library.

@sgraf812 sgraf812 added the changelog-language Language features and metaprograms label Jul 30, 2026
@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 Jul 30, 2026
@mathlib-lean-pr-testing

mathlib-lean-pr-testing Bot commented Jul 30, 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 5fe7f2454c32fe1605c6910f7140ce1f0a04f43b --onto 0bfc3acaef4ed0576307a77fbaa0c6e1a5dca402. You can force Mathlib CI using the force-mathlib-ci label. (2026-07-30 09:07:04)
  • ❗ Mathlib CI can not be attempted yet, as the nightly-testing-2026-07-30 tag does not exist there yet. We will retry when you push more commits. If you rebase your branch onto nightly-with-mathlib, Mathlib CI should run now. You can force Mathlib CI using the force-mathlib-ci label. (2026-07-30 10:29:13)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase 2d0879c245c9804aafe2b9b52dde1eca0712f889 --onto 0bfc3acaef4ed0576307a77fbaa0c6e1a5dca402. You can force Mathlib CI using the force-mathlib-ci label. (2026-07-30 13:23:09)

@leanprover-bot

leanprover-bot commented Jul 30, 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 5fe7f2454c32fe1605c6910f7140ce1f0a04f43b --onto a39eab69e1eee9ad38f4efe507907b1026a77808. You can force reference manual CI using the force-manual-ci label. (2026-07-30 09:07:06)
  • ❗ Reference manual CI can not be attempted yet, as the nightly-testing-2026-07-30 tag does not exist there yet. We will retry when you push more commits. If you rebase your branch onto nightly-with-manual, reference manual CI should run now. You can force reference manual CI using the force-manual-ci label. (2026-07-30 10:29:15)
  • ❗ Reference manual CI will not be attempted unless your PR branches off the nightly-with-manual branch. Try git rebase 2d0879c245c9804aafe2b9b52dde1eca0712f889 --onto a39eab69e1eee9ad38f4efe507907b1026a77808. You can force reference manual CI using the force-manual-ci label. (2026-07-30 13:23:11)

sgraf812 added 6 commits July 30, 2026 12:35
This PR changes the loop invariant of `Std.Internal.Do` from a cursor indexed by the list being iterated to a plain function of the elements consumed so far and the elements remaining. The `for … invariant` clause now binds two lists, `invariant pref suff => …`, in place of the single cursor binder.

`Invariant xs β Pred := List.Cursor xs → β → Pred` becomes `Invariant α β Pred := List α → List α → β → Pred`. The relation `pref ++ suff = xs` moves out of the type and into the hypotheses of the verification conditions, where it already appears as `h : xs = pref ++ cur :: suff`. This removes the `List.Cursor.cast` transports and the `by simp [ForIn.toList_list, h]` property proofs from the specification lemmas, and decouples an invariant's type from the spelling of the list a specification uses: the `forInWithInvariant` gadgets now take `inv : Invariant α β Pred`, naming neither the container nor `ForIn.toList`. `RepeatInvariant`, used for `repeatM`, is already non-dependent, so the two loop forms are now consistent.

`Std.Do`, the legacy library, is unchanged.
Rewrites the `invariant` clauses and `inv` alternatives in the `vcgen` tests and benchmarks from cursor projections (`c.prefix`, `c.suffix`, `c.pos`) to the two list binders.
`Cursor.cast` existed to move a loop invariant between two spellings of the list it ranges over. The non-dependent invariant has no such spelling, so nothing transports cursors any more.
An invariant may constrain the state of the ambient monad rather than a mutable variable of the `do` block, which no test exercised.
This PR names the components of the mutable-variable tuple that the `invariant` clause elaboration builds `mutBinders`, `mutTuplePat` and `mutTupleBinder`, leaving "state" for the state of a stateful `Pred`.
@sgraf812
sgraf812 force-pushed the sg/invariant-no-cursor branch from 19ec7a1 to 6113f93 Compare July 30, 2026 12:51
@sgraf812
sgraf812 marked this pull request as ready for review July 30, 2026 13:02
@sgraf812
sgraf812 requested a review from TwoFX as a code owner July 30, 2026 13:02
@sgraf812
sgraf812 enabled auto-merge July 30, 2026 13:02
@sgraf812
sgraf812 added this pull request to the merge queue Jul 30, 2026
Merged via the queue into master with commit c7673e7 Jul 30, 2026
22 checks passed
@sgraf812
sgraf812 deleted the sg/invariant-no-cursor branch July 30, 2026 13:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog-language Language features and metaprograms 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.

2 participants