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 e5aa71063d
|
| Files | Import difference |
|---|---|
| ../mathlib-ci/scripts/pr_summary/import_trans_difference.sh all | |
| There are 8511 files with changed transitive imports taking up over 371900 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
+ _eps_pos
+ _m_pos
+ aPriv
+ aPrivBothErrors
+ aPrivSilenced
+ bPriv
+ bPrivSilenced
+ f
+ f'
+ fImplicit
+ fImplicit'
+ fLocal
+ fLocalSilenced
+ fNestedBy
+ fProofsInPublic
+ foo
+ fooPub
+ fooThm
+ fα
+ fα'
+ fα''
+ fαPub'
+ fαPub''
+ gImplicit
+ implicitThm
+ sup_aux
+ truncatedSup
+ usePriv
- eps_pos
- m_pos
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
e5aa710).
- +2 new declarations
- −0 removed declarations
+Mathlib.Tactic.PrivateProof.linter.privateProof.warnIfUnnecessary
+Mathlib.Tactic.PrivateProof.privateElabIncrease in strong tech debt: (relative, absolute) = (0.35, 0.35)
| Current number | Change | Type (strong) |
|---|---|---|
| backward.privateInPublic | 367 | -124 |
| backward.privateInPublic.warn | 152 | -47 |
| backward.proofsInPublic | 1 | 1 |
Current commit e5aa71063d
Reference commit 9f7aa3a132
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.py 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).
…f dot notation (data is being constructed classically)
…hen we want to use it in definitions that are not fully ready to remove `backward.privateInPublic`. Note: we also insist on wrapping the proof anyway now (unless it's a free variable), since the user probably wants to see if that'll work.
…hen we want to use it in definitions that are not fully ready to remove `backward.privateInPublic`. Note: we also insist on wrapping the proof anyway now (unless it's a free variable), since the user probably wants to see if that'll work.
|
This pull request has conflicts, please merge |
|
This pull request has conflicts, please merge |
|
This pull request has conflicts, please merge |
|
This pull request has conflicts, please merge |
This PR applies the
privateproof elaborator in #42563 to get rid of some unnecessarybackward.privateInPublic.In addition to manual fixes, this PR runs skimmer to apply the suggestions of temporary Claude-coded linters in #42756, which are not intended to make it into mathlib (at least, not without a human rewrite). These linters (1) find places
privatecan be used (2) find places whereset_option backward.privateInPubliccan now be removed. They produce a couple of false positives, hence the need for human attention I've given to the output.They also identified a couple of cases where
backward.privateInPublicwas acting only as an elaboration-time affordance, and no private-in-public declarations were actually being used in a public position in the final declaration (but theprivateproof elaborator did not immediately apply). This PR therefore also performs some manual fixes to allow us to remove thoseset_options.Dot notation
There is an unfortunate interaction with dot notation affecting certain
Classical.choose(and similar) locations, where noncomputable data is constructed from a proof which can beprivate. Namely, the expected type is not available, causingprivate(andby exact, if you were to write that instead) to fail. However, deliberately insisting on no expected type via(t :)works: e.g.(private <term> :).some. There unfortunately isn't much to do on the elaborator side inprivatethat would fix this, I don't think. But it might make sense to make this more readable somehow (though I'm not sure how).variableissuesvariables are currently elaborated for each declaration in the ambient scope, regardless of theprivate/publicannotations on the declaration(s) they're being elaborated for. This means avariablein apublic sectionthat references a private declaration will silently cause a sorry, and demandbackward.privateInPublicto elaborate successfully. Related lean core issues: leanprover/lean4#14708, leanprover/lean4#14718.Restructuring
public sectionso that it does not includevariableis one way to fix this, and we do this for a couple of files (Mathlib.NumberTheory.NumberField.House; Mathlib.RingTheory.Spectrum.Prime.ChevalleyComplexity; Mathlib.Topology.MetricSpace.GromovHausdorffRealized; Mathlib.CategoryTheory.Galois.Decomposition). In these cases, almost every declaration isprivate. We leave theprivateannotations on for readability (lest they accidentally become public if someone adds apublic sectionlater).macros using private definitions
In Mathlib/Combinatorics/SimpleGraph/Regularity/Bound.lean, we define a macro that refers to two private special-purpose theorems. I make these public but internal (e.g.
m_pos->_m_pos), as is standard best practices for tactic writing.I suspect that the private definitions used by Aesop in
Matroid.Basicshould be treated similarly, but I'm not familiar enough with the area.Misc.
Sometimes we construct both data and proofs with the same
byblock (e.g.,applya data-creating definition then discharge its proof obligations with the rest of the block). This prevents lean from auto-abstracting the proof during elaboration. A couple manual fixes therefore involve putting the proof segments of the tactic block into their ownbyblocks.Sometimes, the
privatefield annotation for structure instances is enough (e.g.fieldFoo := private ...), which is handled specially by lean and is not an instance of the new private proof elaborator.In a handful of cases, we can make partial progress towards removing
backward.privateInPublicby wrapping something withprivatebut still need it for some other reason. In these cases we addset_option linter.privateProof.warnIfUnnecessary falseto silence the warning from theprivateelaborator telling us thatbackward.privateInPublicis currently true.This PR is fully human-reviewed, and all of this text is human-written.
privateelaborator for proofs #42563