Commit graph

12275 commits

Author SHA1 Message Date
Sebastian Ullrich
d33a771ea3
test: always clean full .lake (#13703)
Ensures we don't reuse outdated config oleans
2026-05-12 16:25:00 +00:00
Sofia Rodrigues
8c82f9ed4a
feat: add Locale and LocaleSymbols for configurable date/time formatting (#13567)
This PR adds Locale and LocaleSymbols for configurable date/time
formatting. It also modifies alignedWeekOfMonth and weekOfYear so it
contains a parameter to the first of the week.

This PR is useful for the TR35 formatting PR.
2026-05-12 13:21:25 +00:00
Wojciech Różowski
c04a83a2e5
refactor: turn dupNamespace into a Lean.Linter (#13708)
This PR moves the `dupNamespace` linter from the `EnvLinter` framework
to the `Lean.Linter` (text linter) framework, upstreaming the code from
`mathlib`.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 06:39:08 +00:00
Sofia Rodrigues
f67ea44b6a
feat: add WallTime and simplify Timestamp API (#13675)
This PR adds a `WallTime` type representing a point in time as
nanoseconds since `1970-01-01T00:00:00` local time. It also removes the
`sinceUNIXEpoch` and `AssumingUTC` suffixes because `Timestamp` implies
UTC, and `WallTime` implies it is based on the WallTime epoch (defined
in the comment as `1970-01-01T00:00:00`).

---------

Co-authored-by: Julia Markus Himmel <2065352+TwoFX@users.noreply.github.com>
2026-05-11 23:26:19 +00:00
Joachim Breitner
d055778913
chore: delete flaky tests for now (#13711)
This PR deletes two tests that sometimes timeout (or crash, unclear
without #13710) and I was not able to fix it by EOD.
2026-05-11 19:31:54 +00:00
Mac Malone
f52a18a947
chore: re-enable Lake tests (#13692)
This PR re-enables all of the Lake tests by default. The previous
flakiness appears to have been fixed by #13559, as multiple runs of
#8580 demonstrate. The `LAKE_CI` CMake setting and the `lake-ci` label
is kept to potentially enable expensive Lake tests in the future (e.g.,
the online tests that are not currently run in CI).
2026-05-11 14:56:40 +00:00
Thomas R. Murrills
48ad8401cd
fix: do not modify infotrees in withSetOptionIn (#11313)
This PR ensures that `withSetOptionIn` does not modify the infotrees or
error on malformed option values, and thus avoids panics in linters that
traverse the infotrees with `visitM`.

`withSetOptionIn` is only intended to be used in linters, and thus
should provide the linter action with the infotrees produced during
elaboration without modification. However, `withSetOptionIn` had not
only been modifying the infotrees by elaborating the option, but had
been producing context-free info nodes in doing so. These caused uses of
`visitM` and related functions to panic in typical linters.

Likewise, `withSetOptionIn` also should not cause the linter to error if
somehow it consumes a malformed option value, but instead should fail
silently; the error should (only) be logged during the original
elaboration.

We give an optional flag `(addInfo := true)` to `Elab.elabSetOption`
which controls whether info is added to the infotrees.

To clarify that `withSetOptionIn` is used only in linters, we move it
into `Lean.Linter.Basic`. To avoid import cycles, we move the current
contents of `Lean.Linter.Basic` back to `Lean.Linter.Init`. We also
publicly import both `Lean.Linter.Init` and `Lean.Elab.Command` into
`Lean.Linter.Basic`, meaning that going forward, linter files need only
import `Lean.Linter.Basic` to access the standard linter API.

This was brought up on Zulip
[here](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/bug.3A.20withSetOptionIn.20creates.20context-free.20info.20nodes/with/556905420),
and discussed briefly in office hours.

---------

Co-authored-by: Wojciech Rozowski <wojciech@lean-fro.org>
2026-05-11 11:36:39 +00:00
Joachim Breitner
0c4d2648b5
test: harden cancellation_empty_by against scheduling races (#13704)
This PR fixes issues with flaky cancellation_empty_by test.

The original test gated the runner's `waitFor: blocked` on `t1`'s
`wait_for_cancel_once_async`, which had no causal relationship to
`tracerSuggestion` having actually run inside the empty-`by` snapshot
task. On CI under load the runner could trigger the insert before
`tracerSuggestion` registered its `onSet` callback, leading to
intermittent timeouts.

Add a label-keyed `IO.Promise` registry (`syncPromisesRef`) plus
`getSyncPromise` / `resolveSyncPromise` primitives and a
`wait_for_sync <label>` tactic to `Lean.Server.Test.Cancel`. The
empty-`by` test's `tracerSuggestion` now resolves a sync promise
after registering its onSet, and `t1` waits on that promise before
emitting `blocked`. The empty-`by` example must precede `t1` because
`try?` inside the snapshot task synchronously waits on prior pending
async theorem bodies during library search (likely a separate upstream
issue); with that ordering the test is fully deterministic.

`t1` also drops `wait_for_cancel_once_async` in favor of plain
`trace "blocked"`. The test now also `dbg_trace`s at each sync point
(`tracerSuggestion ready`, `sync received`, `cancelTokenSet`) so the
.out.expected captures the deterministic execution sequence.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 10:34:38 +00:00
Wojciech Różowski
139e6732bd
chore: align cbv tactic with SymM framework conventions (#13682)
This PR tightens how the `cbv` tactic interacts with the `Sym.Simp`
framework. It propagates the `contextDependent` flag through cbv
simprocs so cd-marked sub-results from `simp` are no longer dropped at
congruence and projection sites, and rejects `@[cbv_opaque]` on
`@[reducible]` declarations - `Sym` eliminates reducibles before `cbv`
runs, so the combination has no consistent meaning. With that guarantee
the cbv-specific `unfoldReducible`/`preprocessMVar` clones are removed
in favor of their stock `Sym` counterparts.
2026-05-11 10:04:26 +00:00
Joachim Breitner
2229b077d6
feat: empty by runs try? to suggest a proof (#13430)
This PR makes an empty `by` block run `try?` in the background and
surface its suggestions, while still producing the usual unsolved-goals
diagnostic. The implicit `try?` is informational only — it does not
change elaboration behavior beyond emitting messages. Behaviour is
controlled by a new option `tactic.tryOnEmptyBy`, disabled by default
for now; set it to `true` to opt in. The default may flip in a future
release.

Behaviour summary, when the option is enabled:
* The empty `by` reports unsolved goals immediately, before the
(possibly slow) `try?` has finished.
* The `try?` work is spawned as an asynchronous snapshot task
(`Term.wrapAsyncAsSnapshot` + `Core.logSnapshotTask`), so subsequent
elaboration is not blocked and the suggestions arrive when ready.
* `try?` is gated on its parser infrastructure being available, so
working on the prelude (before `Init.Try` is imported) keeps the regular
empty-`by` behaviour.
* No effect when the empty `by` appears inside a backtracking combinator
(e.g. `first | exact (by) | …`) or when `try?` finds no applicable
suggestion.

Implementation notes:
* `elabEmptyByAsTry` (in `Lean.Elab.Tactic.Try`) is registered as a
second `@[builtin_term_elab byTactic]`, alongside the existing
`elabByTactic` in `Lean.Elab.BuiltinTerm`. The gate
`shouldElabEmptyByAsTry` is checked in both elaborators so the
empty-`by` path takes the `try?` route while non-empty `by` follows the
regular path. The body shared between them is factored as
`elabByTacticCore`. The two-elaborator setup avoids a circular module
dependency between `BuiltinTerm.lean` and `Tactic/Try.lean`; an inline
comment in `Try.lean` explains this.
* A latent bug from #13229 is fixed along the way: `evalSepTactics`
returned at the very top for an empty tactic sequence without resolving
the `tacSnap` promise that `MutualDef.mkTacTask` sets up for `:= by …`
bodies. The dangling promise was harmless in typical use because the
cmd's cancellation token would fire shortly after elaboration and drop
it, but with a slow async snapshot task in the same command (as the
implicit `try?` here) the language-server info-tree walk would block on
it and the editor's Messages view would only update once the task
finished. Resolved at the early-return in `evalSepTactics`.
* The test infrastructure in `Lean.Server.Test.Cancel` gains a
label-keyed `testTasksRef` registry plus `mkTestTask` /
`wait_for_test_task`. The pre-existing `block_until_cancelled` is
reimplemented on top of `mkTestTask` and the redundant
`blockUntilCancelledOnce` ref is removed.

Tests:
* `tests/elab/tryOnEmptyBy.lean`, `tests/elab/try_prelude.lean` —
feature behaviour and prelude gating.
* `tests/server_interactive/cancellation_empty_by.lean` — verifies that
on document re-elaboration `cancelRec` reaches the empty-`by` snapshot's
cancel token registered with `Core.logSnapshotTask`. A
`[try_suggestion]` generator wires the outer cancel token's `onSet` to
resolve a `mkTestTask "T_outer"` promise, and the candidate
`wait_for_test_task "T_outer"` waits on it. If `cancelTk? := none` is
passed to `Core.logSnapshotTask`, `cancelRec` cannot reach the token,
the wait blocks, and the runner times out. If `cancelTk? := none` is
also passed to `wrapAsyncAsSnapshot`, no `onSet` resolver is registered,
the promise drops without resolution, and `wait_for_test_task` surfaces
a `"task dropped"` diagnostic on stderr.
* `tests/server_interactive/cancellation_try_plain.lean` — verifies
cancellation of plain `try?` (no `=>`) when its `[try_suggestion]`
candidate runs synchronously inside `expandUserTactic`, by chaining
through `wait_for_cancel_once_async`'s shared promise. Breaking
`SnapshotTask.cancelRec` to skip walking children causes a runner
timeout.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-11 06:31:42 +00:00
Mac Malone
41ecccec6d
feat: lake: hoist compiled configurations (#13683)
This PR moves the compiled Lake configurations (e.g., `lakefile.olean`)
from the package's `.lake/config` directory to the workspace's
`.lake/config`. This removes a potential source contention between
workspaces sharing a dependency.
2026-05-08 18:00:37 +00:00
Wojciech Różowski
a416b90d22
feat: remove redundant deprecation warnings (#13595)
This PR silences the `Linter.deprecated` warnings inside of definitions
that are themselves deprecated.


Closes #8942.
2026-05-07 15:43:34 +00:00
Sebastian Graf
422920f643
feat: mvcgen', an experimental SymM-based implementation mvcgen (#13644)
This PR adds an experimental tactic `mvcgen'` that will soon replace
`mvcgen`. It has been reimplemented from the ground up using the new
`SymM`-based framework for efficient symbolic evaluation and can
outperform `mvcgen` by a factor of >100x for some synthetic benchmarks.
`mvcgen'` aspires to be feature-complete with `mvcgen`. Known exceptions
currently are join point sharing, introduction of local specs and
smaller bugs.

The implementation of `mvgen'` used to live in the benchmark suite for
rapid prototyping; this commit merely moves it into the Lean toolchain.
Doing so results in an build time instruction count increase in
seemingly unrelated tests such as `elab/delayed_assign//instructions`;
the reason is that the builtin elaborator attribute now pulls in
substantially more import code on startup.

---------

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2026-05-07 12:53:02 +00:00
Sebastian Graf
049b7ebee2
feat: verifiable repeat/while loops (#13209)
This PR adds `whileM`, a counterpart to `Lean.Loop.forIn` that admits a
one-step unfolding lemma `whileM_eq` (impossible to prove for the
original `partial def`). `Lean.Loop.forIn` now expands to `whileM`, so
`repeat`/`while` keep working without source changes, and the
`Spec.whileM`/`Spec.forIn_loop` `@[spec]` theorems let `mvcgen`
discharge their bodies given a Nat variant and an `α ⊕ β` invariant.

`whileM.impl` is still a `partial def`, but returns a `Subtype
(whileM.Pred f a)` whose property pins the value to an `Acc.recOn` term
whenever an `Acc` and a `MonadAttach` witness exist; `whileM_eq`
extracts that property. A `@[implemented_by]` `whileM.erased` keeps the
runtime a tail call after specialization and would be unnecessary if the
compiler were able eta-expand through the trivial `Subtype` structure.
Supporting infrastructure:
`Internal.Ensures`/`MayReturn`/`ErasesTo`/`IsAttach` and `WPAdequate`
for `Id`/`ReaderT`/`StateT`/`ExceptT`/`OptionT`.

The resulting `while` loops take more work to optimize, hence a modest
increase in build time instructions.
2026-05-07 12:48:42 +00:00
Joachim Breitner
9151360469
fix: preserve symbol hover for fun_induction function target (#13678)
This PR ensures that one can hover over the function name in
fun_induction. Fixes #13673

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-05-07 12:09:36 +00:00
Sebastian Ullrich
443615f27e
test: remove printDecls test (#13677)
This is a test from the very beginnings of the elab framework, which has
since become the second-slowest test.
2026-05-07 11:18:33 +00:00
David Thrane Christiansen
5d5642107d
fix: elaborate and render blockquotes in Verso docstrings (#13670)
This PR adds support for blockquotes to Verso docstrings, which had been
missing before. It also substantially improves the robustness of
Verso->Markdown rendering of docstrings, especially the handling of
blockquote line prefixes.
2026-05-06 23:59:11 +00:00
Sebastian Graf
36a54dbe9c
test: mvcgen' with grind should fail when grind fails (#13672)
This PR fixes the semantics of `mvcgen' with grind`: it now logs an
error per VC that `grind` cannot close and throws at the end, instead of
silently leaving the unsolved VC as a residual. The previous
silent-fallback behaviour is preserved as `mvcgen' with (try grind)`,
which `elabPreTac` recognises and routes to the same efficient `.grind`
path with a `silent` flag.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2026-05-06 21:41:38 +00:00
Sebastian Graf
a81628ddbf
test: add BackwardRule.applyChecked debug wrapper for mvcgen' (#13671)
This PR adds a `+debug` config option to `mvcgen'` and a
`BackwardRule.applyChecked` wrapper around `BackwardRule.apply`. On
apply failure with `+debug` set, the wrapper retries on the
`unfoldReducible`-normalized goal type; if the retry succeeds, an
earlier step missed a normalization and `mvcgen'` raises a hard error
naming the rule (auto-derived from `rule.expr.getAppFn` when available)
and showing the original vs. normalized types.

---------

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2026-05-06 21:33:27 +00:00
Joachim Breitner
0c6785c68f
test: simplify cancellation_par test infrastructure (#13663)
This PR replaces the `check_cancel` two-way coordination protocol used
by
`tests/server_interactive/cancellation_par.lean` with a single tactic
`block_until_cancelled "<label>"`. The first invocation for a label
registers
a promise, prints `<label>: blocked`, and loops on
`Core.checkInterrupted`
until the cancel token fires (then `finally` resolves the promise). Any
later
invocation for the same label waits on that promise — so the test only
terminates if the first invocation actually exited the loop. If
cancellation
fails to propagate, the second invocation's `IO.wait` blocks forever and
the
test hangs (timeout = failure), with no false-success path.

The test was disabled in `tests/CMakeLists.txt` due to flakiness in the
old
two-way protocol; this PR re-enables it. Verified that reverting #13428
makes the test deadlock as expected.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-06 19:10:35 +00:00
Sebastian Graf
d34811b5c9
test: tidy Util.lean in the mvcgen' prototype (#13667)
This PR cleans up `tests/bench/mvcgen/sym/lib/VCGen/Util.lean`.

- Drops the four `mkApp{Rev,RevRange,Range,N}S` helpers that were
vendored locally; they are now public in `Lean.Meta.Sym.Internal`
(`Lean.Meta.Sym.AlphaShareBuilder`).
- Moves `Std.HashMap.getDM` out of the root `Std.HashMap` namespace into
`namespace VCGen` and relocates it to `RuleCache.lean`, where its only
call sites live.

---------

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2026-05-06 18:00:25 +00:00
Sebastian Graf
65906d9ccc
test: unfold reducible abbreviations in inline-elaborated invariant values (#13668)
This PR fixes an issue in the `mvcgen'` prototype where user-provided
invariant values were elaborated against a goal type containing
reducible abbreviations like `PostShape.args ps`, baking
`(PostShape.args PostShape.pure)` into the assignment instead of `[]`.

After `tryInlineInvariant` confirms the user tactic assigned the
invariant metavariable, reduce its assignment with `unfoldReducible`.
Fixes the `mvcgen'` migration path for several `tests/elab/*` proofs
that had been blocked on the entailment-phase apply failure.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2026-05-06 17:58:03 +00:00
Kim Morrison
036bd4f0df
fix: withoutExporting around diagnostic reporting (#13630)
This PR fixes an "Unknown constant" error when `set_option diagnostics
true` is enabled in module mode under a `public section`. Diagnostic
output may reference private declarations such as `_match_*` and
`_sparseCasesOn_*` that are recorded in unfold counters; constructing
the message previously failed because the environment was in exporting
mode and could not resolve those names. The diagnostic-printing paths in
`Lean.Meta.Diagnostics.reportDiag` and
`Lean.Meta.Tactic.Simp.Diagnostics.reportDiag` now run under
`withoutExporting`.

Closes https://github.com/leanprover/lean4/issues/13581.

🤖 Prepared with Claude Code

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 13:47:26 +00:00
Henrik Böving
8d2b5d08a1
perf: upgrade to LLVM 22 (#13545)
This PR upgrades LLVM from version 19 to version 22. This brings general
performance improvements of up to 5% instructions depending on
benchmark.
2026-05-06 12:36:06 +00:00
Sebastian Ullrich
e6dfdfdcee
fix: reject attribute uses whose module is reachable only via IR (#13613)
This PR makes the elaborator reject `@[foo]` when the module that
registers `foo` is not visibly imported into the current file but merely
loaded as IR. Previously such uses silently elaborated but led to
divergence of cmdline and server behavior and caused `lake shake --fix`
to flip-flop on successive runs (#13599).
2026-05-06 11:55:43 +00:00
Wojciech Różowski
0e2088fc83
feat: upstream unreachableTactic linter (#13580)
This PR upstreams `unreachableTactic` linter from `batteries` to core
lean.
2026-05-06 11:55:26 +00:00
Wojciech Różowski
ea6e767078
feat: rename --clippy to --extra and run defaults under it (#13649)
This PR renames the `lake lint --clippy` flag to `--extra` and broadens
its scope so that it runs the default builtin linters together with the
non-default ones, instead of only the non-default ones. Use `--lint-all`
to additionally enable any other off-by-default linters.

The matching internal names follow: the namespace `Lean.Linter.Clippy`
becomes `Lean.Linter.Extra`, the option `linter.clippy` becomes
`linter.extra`, and the env-linter attribute form `@[builtin_env_linter
clippy]` becomes `@[builtin_env_linter extra]`.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 20:24:11 +00:00
Mac Malone
ad5ec0e196
feat: user-specified init fn when loading plugins (#13510)
This PR adds the ability to specify a name for the initialization
function of a Lean plugin on load.

* The `Lean.loadPlugin` API has gained a `initFn?` argument that
defaults to `none`. When `none`, the initialization function name will
be inferred from the shared library's name (as before).
* The CLI `--plugin` option can now have a initialization function
specified via `--plugin=path:initFn`.
* The `--setup` JSON configuration now also accepts`{"path": ...,
"initFn": ...}` for plugins.
2026-05-05 20:20:54 +00:00
Joachim Breitner
03bd8847dc
fix: distinguish recursive applications by source position (#13645)
This PR fixes the termination checker reporting errors at the wrong
recursive call site when a function contains structurally-identical
recursive calls at different source locations.

The `_recApp` `MData` attached to recursive applications carried the
attached `Syntax`, but two structurally-equal `MData` wrappers could be
merged by hashconsing/simplification, so the syntax of the first call
ended up associated with both call sites. We now also store the source
byte position as `_recAppPos`, which keeps the wrappers distinct.

Closes #13444.
2026-05-05 16:40:29 +00:00
Sebastian Ullrich
6998af1850
fix: record instances unfolded by wrapInstance as shake dependencies (#13579) 2026-05-05 15:00:23 +00:00
Henrik Böving
aa6fa1cf1a
chore: use the lean-llvm LLVM for benchmarking (#13634)
This PR makes radar use the LLVM that we actually ship to users (stored
at https://github.com/leanprover/lean-llvm). In doing so it also makes
the lake build compatible with lean-llvm, allowing us to do potential
release builds with lake in the future.
2026-05-05 14:26:08 +00:00
Sebastian Graf
42eb0385a5
test: bring Sym-based mvcgen' on par with mvcgen (#13578)
This PR brings the Sym-based `mvcgen'` to feature parity with `mvcgen`;
the only remaining gap is `+jp` (join-point handling).

The slight benchmark regressions are due to simplifying VCs out of
`SPred` form, hitting hardest on cases with linearly many VCs like
`PurePreCond`. The ~10% vcgen slowdown is worth it for the cleaner
user-visible VCs.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-05 13:17:20 +00:00
Joachim Breitner
bd20c51ae4
feat: add trace.Meta.Tactic.simp.backwardDefEq (#13640)
This PR adds a trace event emitted whenever a `dsimp` (or rfl-only
`simp`) rewrite fires
because of a `[backward_defeq]`-tagged theorem (i.e., one that would not
have applied without `set_option backward.defeqAttrib.useBackward
true`).

Useful for finding where downstream code is silently relying on the
backwards escape hatch — a precursor to either re-tagging the lemma as
`[defeq]` or restructuring the proof so it works under the strict
defeq rules.
2026-05-05 13:02:27 +00:00
Leonardo de Moura
8ebd294673
fix: kernel projection panic in Sym.simp match reduction (#13635)
This PR fixes a `Sym.simp` panic ("unexpected kernel projection term
during simplification") that triggered when matcher iota-reduction
exposed kernel `Expr.proj` terms via struct-eta. For example, a `do`
block with a `for` loop whose state is a tuple, where `Sym.simp`
unfolds the equational lemma and then descends into a destructuring
match.
2026-05-05 03:20:20 +00:00
Garmelon
9e5c86eac9
chore: move more radar bench logic to this repo (#13633)
These commands were previously executed in the radar-bench-lean4
repository, but are now moved here for additional control.
2026-05-04 18:21:22 +00:00
Mac Malone
326f43aa3a
fix: lake: meta import transitive import artifacts (#13600)
This PR fixes a Lake issue where the IR for a `meta import`'s transitive
imports was not included in the import artifacts Lake provided to Lean
(e.g., via `--setup`). When using the Lake artifact cache, this could
produce "missing data file" errors due to absent IR.

Closes #13419

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
2026-05-03 17:44:46 +00:00
Leonardo de Moura
316c39ffe4
fix: grind congruence-table invariant for lazy ite branches (#13624)
This PR fixes a `grind` congruence-table invariant violation that could
panic
when an `ite` branch was internalized lazily (after the condition became
`True`
or `False`) and that branch's equivalence class was later merged with
another.

`Internalize.lean` has a special case for `ite` that internalizes only
the
condition; the `then`/`else` branches are skipped and only internalized
later
on demand by `propagateIte`. The on-demand path (`applyCongrFun`) called
`internalize` for the branch but never called `registerParent` to add
the
parent `ite` to the branch's parent set in the e-graph. Subsequent
merges of
the branch's equivalence class then skipped re-hashing the `ite` in the
congruence table, leaving an orphan entry whose `congr` chain no longer
matched
the table's representative.

The fix adds the explicit `registerParent e rhs` that the standard
`for arg in args` loop in `Internalize.lean` would have made for an
ordinary
application argument; we are simply mirroring that pattern lazily. The
same
helper is reused by `propagateDIte`, but with parent registration
disabled
(controlled by a new `ite : Bool` parameter): for `dite` the `rhs`
propagated
upwards is a *constructed* reduction (built via `mkApp` from `e`'s
children,
possibly post-`preprocess`), not a structural argument of `e`, so
registering
`e` as its parent would be incorrect. The lambda branches of a `dite`
are
already eagerly internalized as parents of `e` by `Internalize.lean`, so
this
case does not need the fix.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 17:27:54 +00:00
Leonardo de Moura
ee8acc14e2
fix: grind cast internalization order (#13625)
This PR fixes a `grind` internal error triggered when `cast` (or
`Eq.rec`, `Eq.ndrec`, `Eq.recOn`) is applied to an argument that has not
yet been internalized. `pushCastHEqs` was emitting `e ≍ a` before
internalizing the args of `e`, so the `rhs` of the heq had no enode and
the debug sanity check tripped. The call now runs after the args are
internalized.
2026-05-03 16:32:10 +00:00
Leonardo de Moura
1b23b051f3
fix: missing proof hints in grind propagators (#13623)
This PR fixes proof construction issues in the `grind` projection
propagators.
2026-05-03 14:51:03 +00:00
Leonardo de Moura
2d79ec2883
fix: another grind AC invariant (#13622)
This PR fixes another issue in the `grind` AC invariant checker.
2026-05-03 13:33:13 +00:00
Leonardo de Moura
fe3c7394fd
fix: grind AC invariant (#13614)
This PR fixes the invariant in `grind` AC. equations in the todo queue
are not fully simplified.
2026-05-03 02:19:51 +00:00
Leonardo de Moura
030397785c
fix: missing case in processLevel at SymM (#13612)
This PR improves the universe unifier used by `SymM`.
2026-05-02 17:52:43 +00:00
Sebastian Ullrich
508a113242
feat: add .instances-transparency type-check diagnostics (#13368)
This PR adds infrastructure to help diagnose cases where tactics like
`unfold`
leave the goal in a state that is type-correct only at `.default`
transparency,
causing `rw`/`simp` to fail at `.instances` transparency.

Changes:
- Add a `transparency` parameter to `Meta.check` (defaults to `.all`)
- Add `withInstancesTypeCheckNote` which appends a
lazy note to tactic errors when the target is not type-correct at
`.instances`
- Wrap `rw`, `simp`, `dsimp`, and `simp_all` at the Elab level
- Add opt-in `linter.tacticCheckInstances` that proactively checks every
  tactic goal and reports semireducible defs that should be marked
`@[implicit_reducible]`, using diagnostic counter diffing between
`.default`
  and `.instances` checks
2026-05-02 12:17:51 +00:00
Sebastian Ullrich
4b8e74b27a
chore: disable flaky test (#13603) 2026-05-02 11:58:17 +00:00
Sebastian Ullrich
06ac472859
feat: detect further sub-instances in wrapInstance (#13536)
This PR extends the procedure behind `inferInstanceAs`/`def ...
deriving` to continue recursion through the class graph even when a
(local) instance to wrap was found in order to re-use already-wrapped
instance of subclasses.
2026-05-02 11:55:04 +00:00
Sebastian Ullrich
c53c4b4d2e
fix: prevent private default instances from leaking into public scope (#13596)
This PR fixes private(ly imported) default instances from accidentally
being used in public signatures, leading to follow-up errors.

As reported at
https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Elaboration.20of.20heterogeneous.20mul.20with.20the.20module.20system
2026-05-02 07:53:44 +00:00
David Thrane Christiansen
659249a7df
fix: always fail on unsolved metavariables after Verso docstring elab (#13574)
This PR ensures consistent metavariable behavior between Verso
docstrings and Verso moduledocs by sharing more code between their
elaborators. It also improves the error message when a metavariable leak
is prevented.
2026-05-01 22:34:52 +00:00
Leonardo de Moura
53db221124
fix: disable model-based theory combination in grind derived tactics (#13593)
This PR disables model-based theory combination (`mbtc`) in `grind`'s
`NoopConfig`, which is the base configuration used by the derived
tactics `lia`, `linarith`, `cutsat`, `order`, and `ring`. Without this
fix, these tactics could engage in wasteful reasoning via theory
combination, causing them to run for a long time (or hit the
deterministic timeout) on problems they are not designed to solve. With
this fix, these tactics fail quickly on out-of-scope problems, as
expected.

Closes #13573.
2026-05-01 01:45:17 +00:00
Leonardo de Moura
a9946fe4ac
fix: case-split on arithmetic implications with And/Or antecedents (#13590)
This PR makes `lia` (and `grind`'s arithmetic case-split heuristic)
recognize
implications whose antecedent is an `And` or `Or` of arithmetic
predicates as
relevant case-split candidates. Previously, `Arith.isRelevantPred` only
matched
`Not`, `LE`, `LT`, `Eq`, and `Dvd`. With `splitImp := false` (the
default),
implications `p → q` are added as split candidates only when `p` is
arith-relevant, so a hypothesis like `(b ≤ e ∧ e < b + c → a ≤ e ∧ e < a
+ d)`
was never registered as a candidate. cutsat/lia would then find a
satisfying
assignment for the constraints it had been told about, but that
assignment
would not necessarily satisfy the original implication, yielding the bad
counterexample reported in #13575.

After this change, `isRelevantPred` recurses through `And` and `Or`
(returning
`true` if either operand is relevant), so the implication is split,
modus
ponens fires in the True branch, and cutsat/lia closes the False branch
via the
disjunction over negated atoms.

Closes #13575.
2026-04-30 23:15:34 +00:00
Leonardo de Moura
427e3bcdbc
fix: limit ring solver polynomial degree in grind (#13585)
This PR adds a `ringMaxDegree` configuration option (default `1024`)
that bounds the maximum degree of polynomials processed by the `grind`
ring solver. Equality constraints whose polynomial exceeds this
threshold are discarded (with an issue reported once per goal),
preventing pathological degree explosion on inputs such as `r ^ (2 ^ 250
- 1)`.

This PR also introduces `Poly.simpM?`, a monadic version of `Poly.simp?`
built on the existing safe arithmetic primitives (`mulMonM`, `combineM`,
`mulConstM`) in `Grind.Arith.CommRing.SafePoly`. The previous
reflection-oriented `Poly.simp?` in `Sym.Arith.Poly` lacked the abort
mechanisms needed during proof search, so the simplification path used
by `EqCnstr` now goes through the safe variant. A regression test
`tests/elab/grind_ring_degree_explosion.lean` ensures `grind` fails
quickly on high-degree problems.
2026-04-30 14:00:00 +00:00