looseBVarRange_eq was always a theorem: 28 → 27 - #22
Merged
Conversation
`Lean.Expr.looseBVarRange_eq` is derivable from `Expr.mkData_eq` and
`mkAppData_eq`, both already whitelisted. It becomes a `@[simp] theorem`
with the **identical statement**, so there is no downstream churn.
**Zero cost, unlike the two prior reductions.** Those needed a side
condition consumers then had to discharge; this one needs nothing,
because the condition it requires is the one the axiom already carried.
#print axioms Lean.Expr.looseBVarRange_eq
→ [propext, Quot.sound, Lean.Expr.mkAppData_eq, Lean.Expr.mkData_eq]
No self-reference; no `_native` axiom reachable from `Axioms.lean`.
**The side condition is necessary absolutely, not relative to a model.**
`not_looseBVarRange_eq_unconditional` (in
`Tests/AxiomConsistencyExpr.lean`, already on master) proves
`¬ ∀ e, e.looseBVarRange = e.looseBVarRange'` at `[propext, Quot.sound]`
-- **no axiom at all**, since the cached field is 20 bits and the model
is unbounded. That is the original `False`-proof preserved as a live
theorem, with a companion recording that its witness fails
`BVarBounded`, so the two results cannot collide.
Also recorded in the docstring: **only the `bvar` clause of
`BVarBounded` does any work.** The other ten `Expr.data` clauses pass
arguments built from `looseBVarRange` *field reads*, which the 20-bit
bound covers unconditionally -- so the operative content is exactly
"every `bvar` index is `< 2^20 - 1`", and the recursion exists only to
reach the leaves.
Guard: name out of `axiomWhitelist`, all 8 count sites 28 -> 27, re-pin
note added. The only remaining `28`s are the two history lines.
Verified by building, not reading: `lake build` all default targets,
1291 jobs, exit 0. Guard 1 prints 27; guards 2 and 3 unchanged. Count
re-derived with guard 1's own instrument -- enumerating `axiomInfo`
constants by declaring module -- giving **27**, with
`looseBVarRange_eq` absent from that list and present as a `thmInfo`.
The proof is inline. That inverts no layering: everything it needs is
declared above it in the same file. Its private helpers duplicate facts
`Verify/Expr.lean` also proves, deliberately, for the same reason the
`Verify/Level.lean` re-proof chose duplication -- a shared home would
have had to import the frozen file. The docstring says so.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Owner
Author
|
I approve, merge |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #19. Frozen files change — needs your review. Whitelist 28 → 27.
Lean.Expr.looseBVarRange_eqis derivable fromExpr.mkData_eqandmkAppData_eq, both already whitelisted. It becomes a@[simp] theoremwith the identical statement, so there is no downstream churn.This is the cheapest of the three reductions. The other two needed a side condition that consumers then had to discharge. This one needs nothing — the condition it requires is the one the axiom already carried. It was always a theorem, sitting in the whitelist unexamined.
No self-reference. No
_nativeaxiom reachable fromAxioms.lean.The side condition is necessary absolutely, not relative to a model
not_looseBVarRange_eq_unconditional(already onmaster, inTests/AxiomConsistencyExpr.lean) proves¬ ∀ e, e.looseBVarRange = e.looseBVarRange'at[propext, Quot.sound]— no axiom at all, since the cached field is 20 bits and the model is unbounded. That is the originalFalse-proof preserved as a live theorem, with a companion lemma recording that its witness failsBVarBounded, so the two results cannot collide. A historical inconsistency that can no longer be silently re-broken.A structural finding, recorded in the docstring
Only the
bvarclause ofBVarBoundeddoes any work. The other tenExpr.dataclauses pass arguments built fromlooseBVarRangefield reads, which the 20-bit bound covers unconditionally. So its operative content is exactly everybvarindex is< 2^20 - 1, and the recursion exists only to reach the leaves. It cannot be weakened at the leaves, and need not be strengthened anywhere else.Verification — built, not read
lake build, all default targets, 1291 jobs, exit 0. Zero downstream churn, as the identical-statement claim predicted.axiomInfoconstants by declaring module, not a grep): 27, withlooseBVarRange_eqabsent from that list and present as athmInfo.guard 1: … exactly the 27 frozen axioms ✓; guards 2 and 3 unchanged.Verify/Expr.leanwork, so the two landings are not entangled.Layering
The proof is inline. That inverts nothing — everything it needs is declared above it in the same file. Its private helpers duplicate facts
Verify/Expr.leanalso proves; that is deliberate, for the same reason theVerify/Level.leanre-proof chose duplication (a shared home would have had to import the frozen file). The docstring says so, so nobody "fixes" it later.Where this leaves #19
Class (B) — the only class either historical
False-proof came from — is now exactly the three container axioms (PersistentArray.WF.toList'_push,PersistentHashMap.WF.toList'_insert,WF.find?_eq). They differ in kind from everything closed so far: their right-hand sides are not bit arithmetic but the correctness of a persistent-array and a HAMT algorithm, so exhibiting a model means proving those algorithms correct. That is the whole remaining consistency risk in the file.🤖 Generated with Claude Code