Repository navigation
refactor(Tactic/Linter/MinImports): make the minImports linter stateful - #42186
marcelolynch wants to merge 7 commits into
Conversation
Rewrite the minImports linter with the stateful linter API (leanprover/lean4#14357). The cumulative import data moves from a global IO.Ref into the linter state, which the elaborator threads through the commands of the file. The IO.Ref was unsafe under parallel elaboration, so `#import_bumps` had to set `Elab.async false`; the stateful state is safe and the option stays on. Linter behavior is unchanged: MathlibTest/MinImports.lean passes as is (validated on a nightly-2026-07-27 toolchain). NOTE: CI stays red until the toolchain bump to v4.34.0-rc1, which first provides `registerStatefulLinter`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PR summary 94ebd2a757Import changes for modified filesNo significant changes to the import graph Import changes for all files
|
The new section runs with Elab.async explicitly on: the linter state accumulates correctly across commands, and #import_bumps keeps parallel elaboration enabled. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ionIn' Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ort_bumps Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…r#14581) This PR generalizes `withSetOptionIn` over the result type of the wrapped function. The previous signature only accepted a `CommandElab`, which returns `Unit`. The phases of a stateful linter (leanprover#14357) return values, so they could not use the helper (see for example leanprover-community/mathlib4#42186). All existing call sites instantiate the result type with `Unit` and do not change. A new `resultType` section in `tests/elab/withSetOptionIn.lean` checks the generalized signature. The change preserves behavior. Type inference changes in one corner case: a first-class use with no expected type, where the wrapped function does not determine its result type, now needs a type ascription. Core, Batteries, and Mathlib contain no such use. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This PR generalizes `withSetOptionIn` over the result type of the wrapped function. The previous signature only accepted a `CommandElab`, which returns `Unit`. The phases of a stateful linter (#14357) return values, so they could not use the helper (see for example leanprover-community/mathlib4#42186). All existing call sites instantiate the result type with `Unit` and do not change. A new `resultType` section in `tests/elab/withSetOptionIn.lean` checks the generalized signature. The change preserves behavior. Type inference changes in one corner case: a first-class use with no expected type, where the wrapped function does not determine its result type, now needs a type ascription. Core, Batteries, and Mathlib contain no such use. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Core's `withSetOptionIn` now has an arbitrary result type (leanprover/lean4#14581, in v4.34.0-rc1), so it fits the post phase of a stateful linter. The private polymorphic copy goes away. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
I never know what to think of linter that are implemented in mathlib but are not actually active in mathlib. I would think that they (or at least some of them) are used so rarely that they might as well be deprecated. @thorimur, since you are working on the |
|
I think the I should mention the |
This PR rewrites the
minImportslinter as a stateful linter (leanprover/lean4#14357). The linter behavior does not change. The existing tests inMathlibTest/MinImports.leanpass without changes. The PR adds one test section that setsElab.async trueexplicitly: it checks that the linter accumulates imports correctly under parallel elaboration, and that#import_bumpskeeps parallel elaboration on.The old implementation kept the cumulative imports in a global
IO.Ref. The ref is not safe under parallel elaboration. For this reason,#import_bumpssetElab.async falsefor the rest of the file. The new implementation keeps the same data in the linter state. The elaborator threads the state through the commands of the file, and the data stays correct under parallel elaboration.#import_bumpsdoes not disableElab.asyncanymore.Implementation notes:
#reset_min_importselaborator does nothing. The linter detects the command syntax and clears its own state. The reset works also when the linter option is off, as before.set_option ... inprefixes withwithSetOptionInfrom core. feat: generalize withSetOptionIn to arbitrary result types leanprover/lean4#14581 generalizes the result type of that function, so it accepts the phase of a stateful linter and not only aCommandElab. The generalization ships in v4.34.0-rc1.ImportStateand the linter handle are public. A follow-up can pass the computed import set to theupstreamableDecllinter, which computes the same data a second time today.Measurements on synthetic files (Apple Silicon, 18 cores, medians of 3 runs):
Elab.async trueemits 123 warning lines instead of the correct 11, because parallel lint tasks race on the ref. The new version emits the correct 11 lines.registerStatefulLintershipped in v4.34.0-rc1🤖 Generated with Claude Code