feat: private elaborator for proofs - #42563
Conversation
…via `by as_aux_lemma` Delegating to `by as_aux_lemma => exact @$t` had three problems: * `by` only leaves the exporting context when `backward.proofsInPublic` is `false` (`Lean.Elab.Term.runTactic`), so under that option `private` silently became a no-op and failed to resolve private declarations at all. This contradicted the existing comment stating we deliberately do not check that option. * `@$t` only means "no implicit lambda" for non-identifiers; for an identifier it takes the `elabAtom` branch and makes implicit arguments *explicit*, so `private` broke any lemma with leading implicit arguments. * `by` already abstracts proofs into an auxiliary theorem itself, so `as_aux_lemma` emitted a redundant second one. Elaborate the term outside the exporting context and call `mkAuxTheorem` ourselves instead. This matches what `by exact` does (`exact` is `elabTermEnsuringType` against the goal type, and `runTactic` wraps using the expected type rather than re-inferring), minus the three problems above. `withSynthesize` is required so that synthetic metavariables created while elaborating the term are solved before abstracting; otherwise `mkValueTypeClosure` abstracts them into parameters of the auxiliary theorem and the proof is hoisted back out into the exporting context. Also skip the wrapper for a local hypothesis, pass `cache := !e.hasSorry`, and make the module docstring an actual docstring (`/-!`), which silences a `linter.style.header` warning on every build. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
PR summary 53b0ce2064
|
| Files | Import difference |
|---|---|
| ../mathlib-ci/scripts/pr_summary/import_trans_difference.sh all | |
| There are 8250 files with changed transitive imports taking up over 359885 characters: this is too many to display! | |
You can run this locally from your mathlib4 directory: |
git clone https://github.com/leanprover-community/mathlib-ci.git ../mathlib-ci
Declarations diff (regex)
+ F
+ FEq
+ aPriv
+ bPriv
+ f
+ f'
+ fImplicit
+ fImplicit'
+ fLocal
+ fNestedBy
+ fProofsInPublic
+ foo
+ fooPub
+ fooThm
+ fα
+ fα'
+ fα''
+ fαPub'
+ fαPub''
+ gImplicit
+ implicitThm
+ sup_aux
+ truncatedSup
+ usePriv
You can run this locally as follows
## from your `mathlib4` directory:
git clone https://github.com/leanprover-community/mathlib-ci.git ../mathlib-ci
## summary with just the declaration names:
../mathlib-ci/scripts/pr_summary/declarations_diff.sh <optional_commit>
## more verbose report:
../mathlib-ci/scripts/pr_summary/declarations_diff.sh long <optional_commit>The doc-module for scripts/pr_summary/declarations_diff.sh in the mathlib-ci repository contains some details about this script.
Declarations diff (Lean)
✅ Lean-aware diff — post-build, computed from the Lean environment (commit
53b0ce2).
- +1 new declarations
- −0 removed declarations
+Mathlib.Tactic.PrivateProof.privateElabIncrease in strong tech debt: (relative, absolute) = (1.00, 1.00)
| Current number | Change | Type (strong) |
|---|---|---|
| 685 | 1 | backward.privateInPublic |
| 1 | 1 | backward.proofsInPublic |
Current commit 53b0ce2064
Reference commit 87adeaebd3
This script lives in the mathlib-ci repository. To run it locally, from your mathlib4 directory:
git clone https://github.com/leanprover-community/mathlib-ci.git ../mathlib-ci
../mathlib-ci/scripts/reporting/technical-debt-metrics.sh pr_summary
- The
relativevalue is the weighted sum of the differences with weight given by the inverse of the current value of the statistic. - The
absolutevalue is therelativevalue divided by the total sum of the inverses of the current values (i.e. the weighted average of the differences).
|
I'm not sure if it makes sense to reserve the Also, there is already a |
|
Maybe...but I do think we want to be able to have something that is dedicated to proofs and performs the wrapping that The argument for the current design might look like this: I claim that proofs are qualitatively different when it comes to to wrapping them in aux decls thanks to proof irrelevance, and that wrapping a non-proof is correspondingly a bigger deal (and you should use The argument against is what you said; it's inconsistent. :) Maybe either (1) the error message should point to (EDIT: I've tentatively done (1), at least.) |
|
I think I would prefer (2) because of how general the word |
|
After thinking about it a bit, I do worry that it might become very easy to "hold it wrong" if This is to say that I think it actually is reasonable to disallow |
This PR adds the
private <term>term elaborator which wraps term-mode proofs in a public auxiliary declaration so that they can use private constants in public positions. For example, a term-mode proof appearing in a public declaration's type will error if it uses a private declaration.Currently,
by exactwill wrap the proof in a private declaration asprivatedoes, but sprinkling code withby exacts hurts readability, since it's difficult to tell at a glance what motivated its presence. Also,privatereports when it's unnecessary, unlikeby exact.Disclosure: I had Claude review this before PRing, seeing if I could get rid of elaborating
by. It found a good reason to do so, and made some changes, which I then reviewed and iterated on myself. I've preserved the (only) LLM-generated changes via the authorship of the commit history.