Commit graph

39531 commits

Author SHA1 Message Date
Wojciech Różowski
424fbbdf26
feat: add support to cbv_eval attribute (#12506)
This PR adds the ability to register theorems with the `cbv_eval`
attribute in the reverse direction using the `←` modifier, mirroring the
existing `simp` attribute behavior. When `@[cbv_eval ←]` is used, the
equation `lhs = rhs` is inverted to `rhs = lhs`, allowing `cbv` to
rewrite occurrences of `rhs` to `lhs`.

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

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 12:23:17 +00:00
Markus Himmel
200f65649a
feat: relate HashSet.ofList to a fold (#12521)
This PR shows `HashSet.ofList l ~m l.foldl (init := ∅) fun acc a =>
acc.insert a` (which is "just" the definition).

We also include the analogous statement about `insertMany`, and prove
this lemmas for dependent hash maps, normal hash maps, hash sets, as
well as the raw and extensional versions, and of course we also give the
corresponding tree map statements.
2026-02-17 12:03:01 +00:00
Lean stage0 autoupdater
bfc5d43ad3 chore: update stage0 2026-02-17 12:18:17 +00:00
Henrik Böving
a5d0ab510e
fix: regression caused by LCNF boxing (#12522)
This PR fixes a regression caused by the porting of the IR boxing to the
LCNF boxing pass.
2026-02-17 11:28:25 +00:00
Leonardo de Moura
91bd6e19a7
feat: add Lean name demangler and profiling pipeline (#12517)
This PR adds tooling for profiling Lean programs with human-readable
function names in Firefox Profiler:

- **`script/lean_profile.sh`** — One-command pipeline: record with
samply, symbolicate, demangle, and open in Firefox Profiler
- **`script/profiler/lean_demangle.py`** — Faithful port of
`Name.demangleAux` from `NameMangling.lean`, with a postprocessor that
folds compiler suffixes into compact annotations (`[λ, arity↓]`, `spec
at context[flags]`)
- **`script/profiler/symbolicate_profile.py`** — Resolves raw addresses
via samply's symbolication API
- **`script/profiler/serve_profile.py`** — Serves demangled profiles to
Firefox Profiler without re-symbolication
- **`PROFILER_README.md`** — Documentation including a guide to reading
demangled names

### Example output in Firefox Profiler

| Raw C symbol | Demangled |
|---|---|
| `l_Lean_Meta_Sym_main` | `Lean.Meta.Sym.main` |
| `l_Lean_Meta_foo___redArg___lam__0` | `Lean.Meta.foo [λ, arity↓]` |
| `l_Lean_MVarId_withContext___at__...___spec__2___boxed` |
`Lean.MVarId.withContext [boxed] spec at Lean.Meta.bar[λ, arity↓]` |

Example:

<img width="1145" height="570" alt="image"
src="https://github.com/user-attachments/assets/8d23cc6a-1b89-4c60-9f4a-9f9f0f6e7697"
/>


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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 03:27:58 +00:00
Kim Morrison
642bcdf55a
fix: handle universe polymorphism in ground grind theorems (#12226)
This PR fixes a bug where `grind [foo]` fails when the theorem `foo` has
a different universe variable name than the goal, even though universe
polymorphism should allow the universes to unify.

The issue was in `instantiateGroundTheorem` (used for theorems with no
quantified parameters), which was passing `thm.proof` directly instead
of calling `getProofWithFreshMVarLevels`. This meant ground theorems
retained their original universe level params instead of getting fresh
level metavariables that could unify with the goal's universe levels.

Fixes
https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/grind.20fails.20because.20of.20universe.20variable.20name

🤖 Prepared with Claude Code

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-17 01:51:37 +00:00
Kim Morrison
2a8650f975
fix: gate reference-manual tagging on release notes title correctness (#12512)
This PR fixes a release workflow bug where the reference-manual
repository would get tagged with a stale release notes title (e.g.,
still showing "-rc1" for a stable release).

The root cause was a sequencing issue: `release_steps.py` didn't update
the release notes title when bumping the reference-manual toolchain, and
`release_checklist.py` only checked the title while the bump PR was
open. Once merged, it went straight to tagging without rechecking.

Two fixes:
- `release_checklist.py`: add a title correctness check before tagging
reference-manual (blocks tagging if the title is wrong)
- `release_steps.py`: automatically update the `#doc` title line in the
release notes file when bumping reference-manual (handles both
RC-to-stable and RC-to-RC transitions)

🤖 Prepared with Claude Code

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 01:20:36 +00:00
Nicolas Rouquette
69393c4d9e
fix: add mem_eraseDups lemma for List deduplication (#11811)
This PR proves that membership is preserved by eraseDups: an element
exists in the deduplicated list iff it was in the original.

Includes a helper lemma for the loop invariant of eraseDupsBy.loop to
establish the relationship between membership in the result, remaining
list, and accumulator.

The proof changed compared to the proposal discussed on Zulip:
https://leanprover.zulipchat.com/#narrow/channel/348111-batteries/topic/Where.20should.20List.2Emem_eraseDup.20and.20List.2Emem_eraseDups.20l.2E.2E.2E

Specifically, I could not apply @Rob23oba 's short proof suggestion
because it is located in `src/Init/Data`, a context where the `grind`
strategy is not yet available.

In the Zulip thread, there is a discussion about the
similarities/differences between Lean's `List.eraseDups` and Batteries'
`List.eraseDup`; whether it makes sense to keep both (perhaps with a
suitable renaming of Batterie's definition) or deprecate one (if any, it
would be Batteries' since it is currently unused whereas Lean's is used
across the board in Lean, Batteries, and Mathlib). See the Batteries PR:
https://github.com/leanprover-community/batteries/pull/1580

changelog-library

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

---------

Co-authored-by: Kim Morrison <477956+kim-em@users.noreply.github.com>
2026-02-16 23:11:14 +00:00
Osman Yasar
6833b6dba8
feat: add BitVec.signExtend_extractLsb_setWidth theorem (#11943)
This PR introduces the theorem
`BitVec.sshiftRight_eq_setWidth_extractLsb_signExtend` theorem, proving
`x.sshiftRight n` is equivalent to first sign-extending `x`, extracting
the appropriate least significant bits, and then setting the width back
to `w`.

---------

Co-authored-by: Tobias Grosser <github@grosser.es>
2026-02-16 22:50:10 +00:00
Eric Paul
76c95a085b
chore: remove unused variable in FileMap.ofString (#11986)
Removes the unused `line` variable in `FileMap.ofString`
2026-02-16 22:49:16 +00:00
Henrik Böving
0a19fe7d98
perf: strip unneeded symbols from libleanshared* (#12060)
This PR strips unneeded symbol names from libleanshared.so on Linux. It
appears that on other platforms the symbols names we are interested in
here are already removed by the linker.
2026-02-16 22:48:20 +00:00
Violeta Hernández Palacios
52db0be2b0
feat: define Squash as a Quotient (#12281)
This PR changes the definition of `Squash` to use `Quotient` by
upstreaming
[`true_equivalence`](https://leanprover-community.github.io/mathlib4_docs/Mathlib/Data/Quot.html#true_equivalence)
(now `equivalence_true`) and
[`trueSetoid`](https://leanprover-community.github.io/mathlib4_docs/Mathlib/Data/Quot.html#trueSetoid)
(now `Setoid.trivial`). The new definition is def-eq to the old one, but
ensures that `Squash` can be used whenever a `Quotient` argument is
expected without having to explicitly provide the setoid.

Besides being useful functionality, this makes Mathlib's
[`Trunc`](https://leanprover-community.github.io/mathlib4_docs/Mathlib/Data/Quot.html#Trunc)
completely equivalent to `Squash`. A future Mathlib PR will deprecate
the former in favor of the latter.

Reopened from #6642.

---------

Co-authored-by: David Thrane Christiansen <david@davidchristiansen.dk>
2026-02-16 22:46:43 +00:00
Paul Reichert
af7b3866b2
feat: prove xs.extract start stop = (xs.take stop).drop start for lists (#12359)
This PR deprecates `extract_eq_drop_take` in favor of the more correct
name `extract_eq_take_drop`, so that we'll be able to use the old name
for a lemma `xs.extract start stop = (xs.take stop).drop start`. Until
the deprecation deadline has passed, this new lemma will be called
`extract_eq_drop_take'`.
2026-02-16 22:43:44 +00:00
Paul Reichert
bf8ca518e7
feat: isSome_find? and isSome_findSome? (#12432)
This PR adds the lemmas `isSome_find?` and `isSome_findSome?` to the API
of lists, arrays and vectors.
2026-02-16 22:42:26 +00:00
Kim Morrison
8059477292
fix: auto-update ProofWidgets4 pin in mathlib4 during releases (#12503)
This PR adds automatic ProofWidgets4 version pin updates to
`release_steps.py` when processing mathlib4. ProofWidgets4 uses
sequential version tags (`v0.0.X`) rather than toolchain-based tags
(`v4.X.Y`), so the existing regex that updates dependency versions in
lakefiles doesn't match it. This has caused CI failures in two
consecutive releases where the mathlib4 PR was created with a stale
ProofWidgets4 pin.

Changes:
- `script/release_steps.py`: Add `find_proofwidgets_tag()` to look up
the latest ProofWidgets4 tag compatible with the target toolchain, and
use it to update mathlib4's lakefile automatically
- `doc/dev/release_checklist.md`: Document the ProofWidgets4 pin update
step for mathlib4

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 22:39:22 +00:00
Joachim Breitner
2f8c85af89
fix: ensure etaStruct is enabled during type inference (#12507)
This PR fixes #12495 where equational theorem generation fails for
structurally recursive definitions using a Box-like wrapper around
nested inductives.

## Root Cause

`withInferTypeConfig` (in `InferType.lean`) ensures various MetaM config
settings (`beta`, `iota`, `zeta`, `zetaHave`, `zetaDelta`, `proj`) are
enabled during type inference, but was missing `etaStruct`. When
`inferType` is called from a context where `etaStruct` is disabled —
such as inside `simpMatch` (which sets `etaStruct := .none` via
`SimpM.run` → `withSimpContext`) — `whnf` cannot eta-expand structure
values needed for recursor iota reduction.

Concretely, projecting from a type like `Rec.rec_2 ... base` (where
`base : Box Rec`) requires eta-expanding `base` to `Box.mk base.data` so
the `Box` recursor can reduce. With `etaStruct := .none`,
`toCtorWhenStructure` skips the eta-expansion, leaving `whnf` stuck and
`inferProjType` unable to recognize the resulting type as a structure.

## Fix

Add `etaStruct := .all` to the config settings ensured by
`withInferTypeConfig`, alongside the existing `beta`, `iota`, `zeta`,
`zetaHave`, `zetaDelta`, and `proj` settings. This also allows reverting
the workaround (`try/catch` around `simpMatch?`) that was added in the
first commit.

## Test plan

- [x] Existing test `tests/lean/run/issue12495.lean` passes
- [x] Full test suite (3561 tests) passes with 0 failures

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 20:27:57 +00:00
Henrik Böving
b2446552b4
chore: cleanup backwards compat annotations in the LRAT checker (#12511) 2026-02-16 20:23:27 +00:00
Sebastian Ullrich
440d686313
perf: do not export environment extensions without entries (#12508)
Avoids wasted work in `setImportedEntries`. This is still not ideal as
exts that are set but never/rarely read still have a cost proportional
to the number of imported modules but it's an easy step forward.
2026-02-16 17:34:41 +00:00
Lean stage0 autoupdater
a166d6ee20 chore: update stage0 2026-02-16 16:51:43 +00:00
Sebastian Graf
c5c0ddcc56
test: remove let handling from Sym mvcgen (#12505)
This PR removes the unnecessary and potentially broken handling of
`let`s by zeta-reduction in Sym-based `mvcgen`.
It turns out to be unnecessary for the benchmarks so far, so there is a
lack of motivation to publicize `betaRevS` which would be needed to fix
it.
2026-02-16 15:58:36 +00:00
Leonardo de Moura
9a032cd261
feat: backward.isDefEq.respectTransparency (#12179)
This PR ensures `isDefEq` does not increase the transparency mode to
`.default` when checking whether implicit arguments are definitionally
equal. The previous behavior was creating scalability problems in
Mathlib. That said, this is a very disruptive change. The previous
behavior can be restored using the command
```
set_option backward.isDefEq.respectTransparency false
```
2026-02-16 15:57:21 +00:00
Kim Morrison
4979fa8415
chore: make Rat.abs lemmas protected (#12504)
This PR makes the `Rat.abs_*` lemmas (`abs_zero`, `abs_nonneg`,
`abs_of_nonneg`, `abs_of_nonpos`, `abs_neg`, `abs_sub_comm`,
`abs_eq_zero_iff`, `abs_pos_iff`) protected, so they don't shadow the
general `abs_*` lemmas when the `Rat` namespace is opened in downstream
projects.

All internal references already use the fully qualified `Rat.abs_*`
form, so this is a no-op within lean4 itself.

Suggested by @Rob23oba in
https://github.com/leanprover-community/mathlib4-nightly-testing/pull/177#discussion_r2812925068.

🤖 Prepared with Claude Code

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 15:49:04 +00:00
Paul Reichert
4a9a3eaf6b
feat: Rxx.nodup_toList lemmas and slice/foldl lemmas (#12438)
This PR provides (1) lemmas showing that lists obtained from ranges have
no duplicates and (2) lemmas about `forIn` and `foldl` on slices.
2026-02-16 13:55:11 +00:00
Henrik Böving
620ef3bb86
fix: bring lengthTR lemma back into scope at toArray (#12502)
This PR brings the `length = lengthTR` lemma back into scope after shake
mistakenly removed it.
2026-02-16 13:33:10 +00:00
Sebastian Graf
f084ce1497
test: share benchmark driver for Sym mvcgen; don't measure unfolding (#12501)
This PR shares the driver code from the Sym-based mvcgen benchmarks. It
also moves the `simp only [loop, step]` call out of the measured
section, so that we measure purely the overhead of VC generation.

The new benchmark results are as follows. All measurements for n=1000:

```
baseline_add_sub_cancel:   719.318425 ms, kernel: 382.708178 ms
vcgen_add_sub_cancel:      306.883079 ms, kernel: 455.050825 ms
vcgen_deep_add_sub_cancel: 543.350543 ms, kernel: 896.926298 ms
vcgen_get_throw_set:       669.566541 ms, kernel: 60754.202714 ms
```

Note that `vcgen_add_sub_cancel` sped up by 100% because we no longer
measure unfolding `loop` and `step`. The baseline didn't speed up as
much because it unfolded in the same `Sym.simp` call that also does
other rewrites, so there was no `simp` pass that could be eliminated.
2026-02-16 13:17:00 +00:00
Henrik Böving
838ff5e850
chore: delete commented code (#12498) 2026-02-16 10:27:46 +00:00
Henrik Böving
efcfd967e0
perf: try to inline mix_hash (#12472)
This PR inlines `mix_hash` from C++ which provides general speedups for
hash functions.
2026-02-16 09:02:32 +00:00
Kim Morrison
5c7a508e21
fix: use target type's instances in delta deriving (#12339)
This PR fixes a diamond problem in delta deriving where
instance-implicit class parameters in the derived instance type were
using instances synthesized for the underlying type, not the alias type.

When deriving an instance for a type alias (e.g., `def ENat := WithTop
ℕ`), this caused a diamond when the alias has its own instance for a
dependency class (e.g., `AddMonoidWithOne` from `CommSemiring`) that
differs from the underlying type's instance (e.g.,
`WithTop.addMonoidWithOne`). Instance search would fail because it
expected the alias's instance but the derived instance used the
underlying's.

The fix: after synthesis succeeds, for each instance-implicit class
parameter, re-synthesize for the target type and use that instance if
it's defeq to what we synthesized for the underlying type.

### Example

```lean
class MyBase (α : Type) where value : Nat := 42
class MyHigher (α : Type) [MyBase α] : Prop where prop : True

instance instBaseNat : MyBase Nat := {}
def MyAlias := Nat
instance instBaseMyAlias : MyBase MyAlias := {}  -- Different expression, but defeq

instance instHigherNat : MyHigher Nat where prop := trivial
deriving instance MyHigher for MyAlias
```

**Before**: `instMyHigherMyAlias : @MyHigher MyAlias instBaseNat` →
instance search fails
**After**: `instMyHigherMyAlias : @MyHigher MyAlias instBaseMyAlias` →
instance search succeeds

### Motivation

This fixes the `CharZero ℕ∞` diamond in Mathlib under #12179 where the
derived instance was using `WithTop.addMonoidWithOne` instead of the
`AddMonoidWithOne` from `CommSemiring ℕ∞`.

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-16 00:35:59 +00:00
Kim Morrison
bda15f6c25
chore: revert "feat: add higher-order Miller pattern support in e-matching (#12483)" (#12492)
This PR temporarily reverts #12483, which broke many proofs in Batteries
and Mathlib. We'll restore this once we have fixes in place.
2026-02-15 09:53:55 +00:00
Lean stage0 autoupdater
fb13783f5c chore: update stage0 2026-02-15 03:57:22 +00:00
Kim Morrison
8051e39a17
doc: expand docstring for @[univ_out_params] (#12487)
This PR expands the docstring for `@[univ_out_params]` to explain:

- How universe output parameters affect the typeclass resolution cache
(they are erased from cache keys, so queries differing only in output
universes share entries)
- When a universe parameter should be considered an output (determined
by inputs) vs. not (part of the question being asked)

This came up while adapting Mathlib for lean4#12286 and lean4#12423. We
needed `@[univ_out_params]` on ~19 classes (`Category`,
`HasLimitsOfSize`, `PreservesLimitsOfSize`, `Functor.IsContinuous`,
`UCompactlyGeneratedSpace`, etc.)

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 03:22:42 +00:00
Leonardo de Moura
0d2a511bde
fix: type class resolution cache (#12286)
This PR ensures the type resolution cache properly caches results for
type classe containing output parameters.

It ensures the cache key for a query like
```
HAppend.{0, 0, ?u} (BitVec 8) (BitVec 8) ?m
```
should be independent of the specific metavariable IDs in output
parameter positions. To achieve this, output parameter arguments are
erased from the cache key. Universe levels that only appear in output
parameter types (e.g., ?u corresponding to the result type's universe)
must also be erased to avoid cache misses when the same query is issued
with different universe metavariable IDs.

---------

Co-authored-by: Kim Morrison <kim@tqft.net>
2026-02-15 03:07:15 +00:00
Lean stage0 autoupdater
6a283751b9 chore: update stage0 2026-02-15 02:57:23 +00:00
Leonardo de Moura
fadb1e6b9b
perf: cache for isDefEqI in Sym (#12486)
This PR caches `isDefEqI` results in `Sym`. During symbolic computation
(e.g., VC generators), we find the same instances over and over again.

Performance numbers before/after fr the benchmark
`tests/bench/mvcgen/sym/vcgen_deep_add_sub_cancel.lean`.

| Benchmark | Before (ms) | After (ms) | Speedup |
|-----------|------------|------------|---------|
| goal_100  | 192.1      | 134.1      | 30%     |
| goal_200  | 325.6      | 225.4      | 31%     |
| goal_300  | 490.2      | 333.5      | 32%     |
| goal_400  | 655.6      | 441.9      | 33%     |
| goal_500  | 861.9      | 553.1      | 36%     |
| goal_600  | 1060.6     | 664.5      | 37%     |
| goal_700  | 1166.8     | 818.7      | 30%     |
| goal_800  | 1393.3     | 919.0      | 34%     |
| goal_900  | 1524.2     | 1025.0     | 33%     |
| goal_1000 | 1663.1     | 1141.9     | 31%     |
2026-02-15 02:22:16 +00:00
Leonardo de Moura
97a7fed6c5
chore: add test for issue #11738 (#12485)
Closes #11738
2026-02-15 00:48:34 +00:00
Leonardo de Moura
0721313dcc
chore: add test for issue #11930 (#12484)
Issue has already been fixed

Closes #11930
2026-02-15 00:41:28 +00:00
Leonardo de Moura
022bf2f822
feat: add higher-order Miller pattern support in e-matching (#12483)
This PR adds support for higher-order Miller patterns in `grind`'s
e-matching engine.

Previously, lambda arguments in e-matching patterns were always treated
as `dontCare`, meaning
they could not contribute to matching or bind pattern variables. This
was a significant limitation
for theorems where lambda arguments carry essential structure, such as
`List.foldl`, `List.foldrM`,
or any combinator that takes a function argument.

With this change, when a pattern argument is a lambda whose body
satisfies the **Miller pattern
condition** — i.e., pattern variables are applied only to distinct
lambda-bound variables — the
lambda is preserved as an `ho[...]` pattern. At instantiation time,
these higher-order patterns
are matched via `isDefEq` after all first-order pattern variables have
been assigned by the E-graph.

### Example

```lean
@[grind =] theorem applyFlip_spec (f : Nat → Nat → Nat) (a b : Nat)
    : applyFlip (fun x y => f y x) a b = f b a := sorry
```

The pattern `applyFlip ho[fun x => fun y => #2 y x] #1 #0` captures the
lambda argument
structurally: `#2` (the pattern variable for `f`) is applied to distinct
lambda-bound
variables `y` and `x`. When `grind` encounters `applyFlip (fun x y =>
Nat.add y x) 3 4`,
it binds `f := Nat.add` via `isDefEq` and fires the rewrite.

### Key design decisions

- **Miller condition check**: Only lambdas where at least one pattern
variable appears
in applied Miller position (applied to distinct lambda-bound vars) are
promoted to
  `ho[...]`. Other lambdas remain `dontCare`.
- **Redundancy elimination**: A post-processing pass demotes `ho[...]`
patterns to `dontCare`
if all their pattern variables already appear in non-HO positions of the
same pattern. This
avoids unnecessary `isDefEq` calls when the lambda doesn't contribute
new variable bindings.
- **E-graph bypass**: HO patterns are not internalized into the E-graph.
They are accumulated
during matching and checked via `isDefEq` after the first-order
assignment is complete.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 00:28:03 +00:00
Henrik Böving
c12c783f62
perf: remove the additional relabeling step during AIG to CNF conversion (#12480)
This PR skips the relabeling step during AIG to CNF conversion, reducing
memory pressure.
2026-02-14 17:08:07 +00:00
Leonardo de Moura
57a2dc0146
fix: handle heterogeneous equality in closeGoalWithValuesEq (#12477)
This PR fixes an internal `grind` error where `mkEqProof` is invoked
with terms of different types. When equivalence classes contain
heterogeneous equalities (e.g., `0 : Fin 3` and `0 : Fin 2` merged via
`HEq`), `closeGoalWithValuesEq` would call `mkEqProof` on terms with
incompatible types, triggering an internal error.

Closes #12140

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 07:12:01 +00:00
Lean stage0 autoupdater
d77efe6a5f chore: update stage0 2026-02-14 05:47:52 +00:00
Leonardo de Moura
cce6ce9577
fix: treat outParam arguments as support in e-matching patterns (#12476)
This PR fixes #12245 where `grind` works on `Fin n` but fails on `Fin (n
+ 1)`.

The `outParam` argument (e.g., the `range` parameter of `ToInt`) was
included as a relevant position in the e-matching pattern. The `grind`
normalizer rewrites `↑(n + 1)` to `↑n + 1` inside the range expression,
causing the pattern to no longer match. Since `outParam` arguments are
uniquely determined by type class resolution, they can be safely
wildcarded in patterns — the same reasoning that already applies to
instance-implicit arguments.

Reproducer from the issue:
```lean
example {n : Nat} {a : Fin (n + 1)} {b : Nat} (hb : b < n + 1)
    (h : (a : Nat) < b) : a < ⟨b, hb⟩ := by grind -- fails without fix
```

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 05:05:56 +00:00
Leonardo de Moura
103ed5b54b
fix: handle delayed mvar assignments in grind when hypotheses contain mvars (#12475)
This PR fixes `grind` failing when hypotheses contain metavariables
(e.g., after `refine`). The root cause was that `abstractMVars` in
`withProtectedMCtx` only abstracted metavariables in the target, not in
hypotheses, creating a disconnect in grind's e-graph.

The fix removes `abstractMVars` and instead resolves delayed
metavariable assignments before exiting `withNewMCtxDepth`.
`instantiateMVars` refuses to resolve a delayed assignment when the
pending assignment is non-ground (contains unassigned expression
metavariables). This function converts such delayed assignments to
regular ones using `LocalContext.mkLambda`, allowing `instantiateMVars`
to resolve them via beta reduction. The mvar internalization warning is
also removed since grind now handles mvars.

Closes #12242

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 04:28:06 +00:00
Leonardo de Moura
187a8c1ce3
fix: handle non-internalized terms in semiring reifier (#12474)
This PR fixes a panic in `grind` where `sreifyCore?` could encounter
power subterms not yet internalized in the E-graph during nested
propagation. The ring reifier (`reifyCore?`) already had a defensive
`alreadyInternalized` check before creating variables, but the semiring
reifier (`sreifyCore?`) was missing this guard. When `propagatePower`
decomposed `a ^ (b₁ + b₂)` into `a^b₁ * a^b₂` and the resulting terms
triggered further propagation, the semiring reifier could be called on
subterms not yet in the E-graph, causing `markTerm` to fail.

Closes #12428

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

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 01:08:42 +00:00
Leonardo de Moura
e579dfdb14
fix: assertion violation in mkEqProofImpl (#12473)
This PR fixes an assertion violation in `grind` reported at #12246 This
assertion fails when in examples containing heterogenous equalities with
elements of different types (e.g., `Fin n` and `Fin m`) attached to the
same theory solver.

Closes #12246
2026-02-14 00:43:15 +00:00
Kim Morrison
c1ad6aa0db
fix: disable order and funCC modules in NoopConfig (#11744)
This PR fixes a bug where `lia` was incorrectly solving goals involving
ordered types like `Rat` that it shouldn't handle. The `lia` tactic is
intended for linear integer arithmetic only.

The fix adds `order := false` and `funCC := false` to `NoopConfig`,
which is the base configuration for `CutsatConfig` (used by `lia`).

Closes
https://leanprover.zulipchat.com/#narrow/channel/113488-general/topic/releases.20of.20new.20Lean.20versions/near/564688881

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 20:41:12 +00:00
Paul Reichert
c6f4fa8678
fix: inherit correct docstring (#12468)
This PR fixes the docstring of `HashMap.diff`.
2026-02-13 16:20:41 +00:00
Paul Reichert
db9293ee3b
fix: remove redundant namespace (#12454)
This PR removes several duplicated namespaces such as in
`Vector.Vector.toList_zip`.
2026-02-13 14:51:59 +00:00
Wojciech Różowski
dae150a976
fix: handle AppBuilderException in cbv tactic if the projection function is dependent (#12460)
This PR fixes an `AppBuilder` exception in the `cbv` tactic when
simplifying projections whose projection function is dependent (closes
#12457).

Previously, `handleProj` unconditionally used `mkCongrArg` to prove `e.i
= e'.i` from `e = e'`, but `mkCongrArg` requires a non-dependent
function. For dependent projections (e.g., `fun x => x.2 : (x :
String.Slice) → x.1.Pos`), this would fail.

Now, `handleProj` first checks whether the projection function type is
non-dependent (a simple arrow). If so, it proceeds with `mkCongrArg` as
before. Otherwise, it falls back to:
1. Attempting to reduce the projection directly.
2. If reduction fails, using a heterogeneous congruence lemma
(`mkHCongr`) converted to an equality via `mkEqOfHEq`, provided the
original and rewritten struct are definitionally equal.
2026-02-13 14:21:13 +00:00
Wojciech Różowski
f3b8f76ec4
test: add cbv benchmark for evaluating Decidable.decide (#12467)
This PR adds a benchmark for `cbv` tactic for evaluating
`Decidable.decide` for a `Decidable` instance for a problem of checking
if a number is not a prime power.

The test has been inspired by a recent discussion on the [leanprover
zulip](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Can't.20decide.20if.2015.20is.20a.20prime.20power/with/572513330).
2026-02-13 13:25:35 +00:00
Henrik Böving
6ae413a56a
perf: make proper use of deletes in bv_decide LRAT checking (#12406)
This PR implements two changes to LRAT checking in `bv_decide`:
1. The LRAT trimmer previously used to drop delete instructions as we
did not act upon them in a meaningful way (as explained in 2). Now it
figures out the earliest point after which a clause may be deleted in
the trimmed LRAT proof and inserts a deletion there.
2. The LRAT checker takes in an `Array IntAction` and explodes it into
an `Array DefaultClauseAction` before passing it into the checking loop.
`DefaultClauseAction` has a much larger memory footprint compared to
`IntAction`. Thus materializing the entire proof as
`DefaultClauseAction` upfront consumes a lot of memory. In the adapted
LRAT checker we take in an `Array IntAction` and only ever convert the
step we are currently working on to a `DefaultClauseAction`. In
combination with the fact that we now insert deletion instructions this
can drastically reduce memory consumption.

In SMT-LIB's 20210312-Bouvier/vlsat3_a11.smt2 memory consumption went
from 8GB+ to 3.7GB through this combination of changes.
2026-02-13 13:11:51 +00:00