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>
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>
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>
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>
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>
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>
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>
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>
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
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.
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.
This PR fixes two issues discovered during the first test of the revised
nightly release workflow
(https://github.com/leanprover/lean4/pull/12461):
**1. Date logic:** The `workflow_dispatch` path used `date -u +%F`
(current UTC date) to find the base nightly to revise. If the most
recent nightly was from yesterday (e.g. `nightly-2026-02-12`) but UTC
has rolled over to Feb 13, the code would look for `nightly-2026-02-13`,
not find it, and create a fresh nightly instead of a revision. Now finds
the latest `nightly-*` tag via `sort -rV` and creates a revision of
that.
**2. Mathlib trigger:** The "Update toolchain on mathlib4's
nightly-testing branch" step was broken in two ways:
- Workflow renamed: `nightly_bump_toolchain.yml` →
`nightly_bump_and_merge.yml` (leanprover-community/mathlib4#34827)
- `MATHLIB4_BOT` PAT expired after mathlib migrated to GitHub Apps
(leanprover-community/mathlib4#34751)
- Replace with `actions/create-github-app-token` using the
`mathlib-nightly-testing` app, matching the pattern used in mathlib4's
own workflows.
🤖 Prepared with Claude Code
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This adds the ancillary materials for the IJCAR 2026 grind paper to
`doc/examples/IJCAR2026/`.
- `examples.lean`: interactive examples from the paper
- `analyze_grind_loc.py`: script used for the evaluation section
(analyzing grind adoption LoC changes in mathlib)
🤖 Prepared with Claude Code
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This PR adds support for manually re-releasing nightlies when a build
issue or critical fix requires it. When a `workflow_dispatch` triggers
the nightly release job and a `nightly-YYYY-MM-DD` tag already exists,
the CI now creates `nightly-YYYY-MM-DD-rev1` (then `-rev2`, etc.)
instead of silently skipping.
### Lake `ToolchainVer`
- Extend `ToolchainVer.nightly` with an optional `rev : Option Nat`
field
- Parse `-revK` suffixes from nightly tags in `ofString`
- Ordering: `nightly-YYYY-MM-DD` < `nightly-YYYY-MM-DD-rev1` < `-rev2` <
`nightly-YYYY-MM-DD+1`
- Round-trip: `toString (ofString s) == s` for both variants
### CI workflow
- "Set Nightly" step probes existing tags on `workflow_dispatch` to find
next available `-revK`
- Scheduled nightlies retain existing behavior (skip if commit already
tagged)
- Changelog grep updated from `nightly-[-0-9]*` to `nightly-[^ ,)]*` to
match `-revK` suffixes
### `lean-bisect`
- Updated `NIGHTLY_PATTERN` regex, sort key, error messages, and help
text
### Companion PRs
- https://github.com/leanprover-community/mathlib4/pull/35220: update
`nightly_bump_and_merge.yml` tag grep and `nightly_detect_failure.yml`
warning message
-
https://github.com/leanprover-community/leanprover-community.github.io/pull/787:
update `tags_and_branches.md` documentation
🤖 Prepared with Claude Code
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This PR bounds-checks `constants.size` directly instead of
`constNames.size` in `LazyDiscrTree.loadImportedModule`, eliminating the
unsafe `constants[i]!` access and the intermediate `constNames[i]`
lookup. The constant name is obtained from `constInfo.name` instead.
🤖 Prepared with Claude Code
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This PR verifies all of the `String` iterators except for the bytes
iterator by relating them to `String.toList`.
Along the way we define `String.posLE` and `String.posLT` analogously to
`String.posGE` and `String.posGT` and redefine `String.prev` to go
through `String.posLT`.
We also define and verify `String.positionsFrom` and
`String.revPositionsFrom`, which are the obvious generaliziations of
`String.positions` and `String.revPositions` starting at a positions
other than the start/end.
Finally, we get various lemmas about strings and positions, including
some nice induction principles `String.Pos.next_induction` and
`String.Pos.prev_induction`.
Of course, we also have all of the analogous results for `String.Slice`.
This is a mitigation for the fact that the upfront noncomputable checker
currently doesn't error out early enough in certain situations so we
violate invariants later on.
This PR adds a simplification rule for `Task.get (Task.pure x) = x` into
the LCNF simplifier. This
ensures that we avoid touching the runtime for a `Task` that instantly
gets destructed anyways.
This PR changes the way artifacts are transferred from the local Lake
cache to a local build path. Now, Lake will first attempt to hard link
the local build path to artifact in the cache. If this fails (e.g.,
because the cache is on a different file system or drive), it will
fallback to pre-existing approach of copying the artifact. Lake also now
marks cache artifacts as read-only to avoid corrupting the cache by
writing to a hard linked artifact.
Lake will also hard link binary artifacts into the cache. If this fails,
it will similarly fall back to copying them. Text artifacts are always
copied, not linked, as the line endings in the cache copy are
normalized.
This PR adds two more benchmarks for the Sym-based mvcgen prototype in
the style of `add_sub_cancel`.
The first is `deep_add_sub_cancel`, which is like `add_sub_cancel` but
with a much deeper monad stack:
```lean
abbrev M := ExceptT String <| ReaderT String <| ExceptT Nat <| StateT Nat <| ExceptT Unit <| StateM Unit
```
By specializing the specs for `get` and `set`, we get competitive
performance:
```
goal_100: 180.365086 ms, kernel: 79.634989 ms
goal_200: 313.465611 ms, kernel: 187.808631 ms
goal_300: 478.278585 ms, kernel: 270.210634 ms
goal_400: 638.884320 ms, kernel: 380.381127 ms
goal_500: 759.802772 ms, kernel: 472.662882 ms
goal_600: 933.575180 ms, kernel: 649.040746 ms
goal_700: 1174.367200 ms, kernel: 759.470010 ms
goal_800: 1298.866482 ms, kernel: 864.420171 ms
goal_900: 1475.315552 ms, kernel: 1008.662783 ms
goal_1000: 1627.957444 ms, kernel: 1078.627830 ms
```
Recall that `add_sub_cancel` had `goal_1000: 824.476962 ms, kernel:
477.069045 ms`, but that doesn't need to repeatedly unwrap 3 layers of
the monad.
The second benchmark is `get_throw_set`. Its kernel is
```lean
def step (lim : Nat) : ExceptT String (StateM Nat) Unit := do
let s ← get
if s > lim then
throw "s is too large"
set (s + 1)
def loop (n : Nat) : ExceptT String (StateM Nat) Unit := do
match n with
| 0 => pure ()
| n+1 => loop n; step n
def Goal (n : Nat) : Prop := ⦃fun s => ⌜s = 0⌝⦄ loop n ⦃⇓_ s => ⌜s = n⌝⦄
```
It will generate `n+1` VCs. We get `n` VCs of the form
```
s✝ : Nat
_ : ¬0 < s✝
...
_ : n < s✝ + 1 ...<n times>... + 1
⊢ ⌜s✝ = 0⌝ ⊢ₛ ⌜False⌝ (s✝ + ...<n times>...)
```
and one VC of the form
```
⌜s✝ = 0⌝ ⊢ₛ ⌜s✝ + 1 + <n times> ... + 1 = n⌝
```
which can be discharged by `grind`, but presently are discharged with
`sorry`.
Statistics:
```
goal_100: 209.435869 ms, kernel: 128.768919 ms
goal_200: 386.639441 ms, kernel: 482.244717 ms
goal_300: 559.795137 ms, kernel: 1251.777405 ms
goal_400: 753.243978 ms, kernel: 3020.878177 ms
goal_500: 1014.939522 ms, kernel: 5182.120327 ms
goal_600: 1229.173622 ms, kernel: 9296.551442 ms
goal_700: 1410.024180 ms, kernel: 16655.954682 ms
goal_800: 1684.059305 ms, kernel: 32065.951705 ms
goal_900: 1905.602401 ms, kernel: 55299.942894 ms
goal_1000: 2172.823244 ms, kernel: 84082.492485 ms
```
Need to look at kernel times here, but tactic time looks about alright.
Using `grind` to discharge just `n=100` goals took 8s.
This PR uses `getImpureSignature?` instead of the `findEnvDecl` from IR
in the LCNF compiler. We
were previously still relying on the IR function because only IR
contained proper borrow
annotations. Now we infer the borrow annotations on the LCNF level and
can thus use the LCNF
signatures.
This PR adds the attribute `@[univ_out_params]` for specifying which
universe levels should be treated as output parameters. By default, any
universe level that does not occur in any input parameter is considered
an output parameter.
This PR verifies the `String.Slice.splitToSubslice` function by relating
it to a model implementation `Model.split` based on a
`ForwardPatternModel`.
The proof is generic, so it works for splitting by characters, strings
etc.
From this, we will be able to give user-facing API lemmas for
`String.split` and friends in future PRs.
We also move the verification of string patterns from
`String.Slice.Pattern` to `String.Slice.Pattern.Model` to achieve better
separation between code that users run in their programs and code that
only supports the theory.
This PR changes the proof for `Char.toUpper` to make it easier to
typecheck for external checkers (nanoda in particular).
---------
Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
This PR removes the uses of `shared_timed_mutex` that were introduced
because we were stuck on C++14
with the `shared_mutex` available from C++17 and above.
This PR adds the lemma `Acc.inv_of_transGen`, a generalization of
`Acc.inv`. While `Acc.inv` shows that `Acc r x` implies `Acc r y` given
that `r y x`, the new lemma shows that this also holds if `y` is only
*transitively* related to `x`.
This PR sets the `irreducible` attribute before generating the equations
for recursive definitions. This prevents these equations to be marked as
`defeq`, which could lead to `simp` generation proofs that do not type
check at default transparency.
This issue is surfacing more easily since well-founded recursion on
`Nat` is implemented with a dedicated fix point operator (#7965). Before
that, `WellFounded.fix` was used, which is inherently not reducing, so
we did get the desired result even without the explicit reducibility
setting.
Fixes#12398.
This PR refactors the main loop of the `cbv` tactic. Rather than using
multiple simprocs, a central pre simproc is introduced. Moreover, let
expressions are no longer immediately zeta-reduced due to performance on
one of the benchmarks (`leroy.lean`).
Stacked on top of #12416
This PR introduces `Rat.abs` and adds missing lemmas about `Int` and
`Rat`.
For `Int`:
- Lemmas about the interaction of negation and order: `neg_le_iff`,
`le_neg_iff`, `neg_lt_iff`, `lt_neg_iff`
For `Rat`:
- Declaration of `Rat.abs`
- Lemmas for `Rat.abs`, `Rat.floor` and `Rat.ceil`
- More basic lemmas that would all be provable with `grind` but might
still be good to have in the library
- Type class instances: `Std.Associative`, `Std.Commutative`,
`Std.LawfulIdentity` for addition
This PR adds a finishing `decide_cbv` tactic, which applies
`of_decide_eq_true` and then tries to discharge the remaining goal using
`cbv`.
Stacked on top of #12408.
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This PR adds caching to `replaceRecApps`, the procedure responsible for
replacing recursive applications for wellfounded recursion, improving
performance when many references to the same recursive call exist, e.g.
when recursive calls exist in proof terms.
Closes#12404
---------
Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
This PR adds a user facing `cbv` tactic that can be used outside of the
`conv` mode.
Example usage:
```lean4
example : "hello" ++ " " ++ "world" = "hello world" := by cbv
```
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This PR gives a proof of `LawfulToForwardSearcherModel` for `Slice`
patterns, which amounts to proving that our implementation of KMP is
correct.
Note that this PR also changes the KMP implementation to make it
slightly more efficient and easier to verify. I also have a correctness
proof for the old implementation, so there were no bugs in the old
implementation.
This PR fixes a bug in `mvcgen` caused by incomplete `match` splitting.
In particular, if a program `match s with ...` matches on a state
variable `s` (presumably the result of a call to `get`), then `s` will
also occur in the stateful goal `H ⊢ₛ wp⟦match s with ...⟧ Q s`
*outside* the program expression; this was not anticipated before.
This PR adds `LawfulOrderOrd` instances for `Nat`, `Int`, and all
fixed-width integer types (`Int8`, `Int16`, `Int32`, `Int64`, `ISize`,
`UInt8`, `UInt16`, `UInt32`, `UInt64`, `USize`). These instances
establish that the `Ord` instances for these types are compatible with
their `LE` instances. Additionally, this PR adds a few missing lemmas
and `grind` patterns.
This PR changes the alters the file format of outputs stored in the
local Lake cache to include an identifier indicating the service (if
any) the output came from. This will be used to enable lazily
downloading artifacts on-demand during builds.
This PR adds comprehensive test running instructions to
`.claude/CLAUDE.md`,
replacing the single `test_single.sh` example with the full range of
test
commands documented in `doc/dev/testing.md`: full suite, filtered by
name,
rerun failures, and direct ctest usage.
🤖 Prepared with Claude Code
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This PR is similar to #12403.
We previously conjectured that "all type class fields that are types
should be marked as reducible." The problem is that propositions are
types, but they are also used as data (with `Decidable`). For example,
we often see the proposition `x <= y` as a Boolean. So, we refined the
conjecture to:
"All type class fields that are types (and not propositions) should be
marked as reducible."
This PR adds `mvcgen` support for specifications in the local context.
Example:
```lean
import Std.Tactic.Do
open Std.Do
set_option mvcgen.warning false
def foo (x : Id Nat → Id Nat) : Id Nat := do
let r₁ ← x (pure 42)
let r₂ ← x (pure 26)
pure (r₁ + r₂)
theorem foo_spec
(x : Id Nat → Id Nat)
(x_spec : ∀ (k : Id Nat) (_ : ⦃⌜True⌝⦄ k ⦃⇓r => ⌜r % 2 = 0⌝⦄), ⦃⌜True⌝⦄ x k ⦃⇓r => ⌜r % 2 = 0⌝⦄) :
⦃⌜True⌝⦄ foo x ⦃⇓r => ⌜r % 2 = 0⌝⦄ := by
mvcgen [foo, x_spec] <;> grind
def bar (k : Id Nat) : Id Nat := do
let r ← k
if r > 30 then return 12 else return r
example : ⦃⌜True⌝⦄ foo bar ⦃⇓r => ⌜r % 2 = 0⌝⦄ := by
mvcgen [foo_spec, bar] -- unfold `bar` and automatically apply the spec for the higher-order argument `k`
```
This PR improves the slice API with lemmas for `drop`/`take` operations
on `Subarray` and more lemmas about `Std.Slice.fold`, `Std.Slice.foldM`
and `Std.Slice.forIn`. It also changes the `simp` and `grind`
annotations for `Slice`-related lemmas. Lemmas converting between slices
of different shapes are no longer `simp`/`grind`-annotated because they
often complicated lemmas and hindered automation.
This PR adds a custom simproc to handle `Decidable.rec`, where we force
the rewrite in the argument of the `Decidable` type, that normally is
not rewritten due to being a subsingleton.
Closes#12386
This PR develops custom simprocs for dealing with `ite`/`dite`
expressions in `cbv` tactics, based on equivalent simprocs from
`Sym.simp`, with the difference that if the condition is not reduced to
`True`/`False`, we make use of the decidable instance and calculate to
what the condition reduces to.
Stacked on top of #12391.
This PR adds `IO.FS.Metadata.numLinks`, which contains the number of
hard links to a file.
This changes the implementation of `System.FilePath.metadata` and
`System.FilePath.symlinkMetadata` to use libuv. Otherwise, `st_nlink`
was not properly set on Windows. This also has the side benefit of
provided sub-second precision for file times on Windows (fulfilling an
old TODO). Also, while libuv supports `lstat` for Windows, enabling that
is left to a future PR.
This PR fixes a platform inconsistency in `IO.FS.removeFile` where it
could not delete read-only files on Windows.
The implementation now uses `uv_fs_unlink` instead of `std::remove`, as
libuv can delete read-only files. The PR also fixes a inconsistency in
`IO_test.lean` where it would generate files in the wrong directory when
run interactively.
---------
Co-authored-by: Markus Himmel <markus@himmel-villmar.de>
This PR fixes an issue in LCNF simp where it would attempt to act on
type incorrect `cases`
statements and look for a branch, otherwise panic. This issue did not
yet manifest in production as
various other invariants upheld by LCNF simp help mask it but will start
to become an issue with the
upcoming changes.
This is the proper fix for #6957.
This PR provides a `LawfulForwardPatternModel` instance for string
patterns, i.e., it proves correctness of the `dropPrefix?` and
`startsWith` functions for string patterns.
Note that this is "just" the correctness proof; there isn't a way to
actually use it yet. API lemmas will follow.
This PR adds identifying information about a module available to `lean`
(e.g., its name and package identifier) to the module's dependency
trace. This ensures modules with different identification have different
input hashes even if their source files and imports are identical.
This PR adds a few unification hints that we will need after
`backward.isDefEq.respectTransparency` is `true` by default.
See #12338
It was part of #12179.
This PR makes disabling the artifact cache (e.g., via
`LAKE_ARTIFACT_CACHE=false` or `enableArtifactCache = false`) now stop
Lake from fetching from the cache (whereas it previously only stopped
writing to it).
There are now 3 possible configuration of the local artifact cache for a
package:
* `true`: Artifacts will be fetched from the cache before building (if
available) and built artifacts will be cached.
* `false:`: Lake will neither fetch artifacts from the cache or store
them into it.
* **default** (no configuration set): Lake will fetch artifacts from the
cache but not store them into it. A key motivation for this is to, by
default, reuse artifacts downloaded into the cache from a remote
service.
This PR tags `List.reduceOption` with `@[expose]`. #12348 accidentally
moved the definition out of an `@[expose] section` which caused problems
in mathlib because `List.reduceOption` was expected to be exposed.
This PR extends shake with tracking of attribute names passed to
`simp`/`grind`.
On the way there, it also fixes `register_simp/grind_attr` uses outside
`public meta section` as well as go-to-definition on declaration-level
uses of the created attributes (tactic-level goto would be a separate
todo).
This PR moves the elaboration of structure/class Verso docstrings until
after the fact that it's a class is registered, so code samples in the
docstring can use it as a class. Redundant addition of structure and
constructor docstrings are also removed, because they're already handled
in MutualInductive.lean.
Closes#11651
This PR uses an `Array` instead of a `List` to store the clauses in
`Std.CNF`. This reduces the memory footprint and pressure on the
allocator, leading to noticeable performance changes with gigantic CNFs.
This PR treats the first character of the first line of a docstring as
being in the leftmost column, even if it physically is not. This allows
left-column items like headers to be used even after spaces. It also
detects the indentation of the entire docstring, using it as the
zero-point for indentation sensitive syntax such as headers.
Closes#12067.
This PR fixes poor error reporting from Verso docstrings. Before, if the
Verso parser didn't consume the whole docstring, then Lean would try to
parse the closing -/ and fail; this would lead to backtracking and an
assumption that the docstring must be non-Verso, with only the non-Verso
commands like #guard_msgs as possibilities. Now, the input is always
consumed.
Closes#12118.
This PR implements better support for unfolding class fields marked as
`reducible`. For example, we want to mark fields that are types such as
```lean
MonadControlT.stM : Type u -> Type u
```
The motivation is similar to our heuristic that type definitions should
be abbreviations.
Now, suppose we want to unfold `stM m (ExceptT ε m) α` using the
`.reducible` transparency setting, we want the result to be `stM m m
(MonadControl.stM m (ExceptT ε m) α)` instead of
`(instMonadControlTOfMonadControl m m (ExceptT ε m)).1 α`. The latter
would defeat the intent of marking the field as reducible, since the
instance `instMonadControlTOfMonadControl` is `[instance_reducible]` and
the resulting term would be stuck when using `.reducible` transparency
mode.
**Remark**: This feature introduces a few breakages in core and Mathlib.
So, it is disabled for now in this PR. To enable, we must use
`set_option backward.whnf.reducibleClassField true`
This PR adds two benchmarks (sieve of Eratosthenes, removing duplicates
from the list) and one test (a function with sublinear complexity
defined via well-founded recursion evaluated on large naturals with up
to `60` digits).
The tests have been suggested by @b-mehta.
This PR changes the semantics of `inline` annotations in the compiler.
The behavior of the original `@[inline]` attribute remains the same but
the function `inline` now comes with a restriction that it can only use
declarations that are local to the current module. This comes as a
preparation to pulling the compiler out into a separate process.
Closes: #12334
This PR changes the handling of over-applied cases expressions in
`ToLCNF` to avoid generating function declarations that are called
immediately. For example, `ToLCNF` previously produced this:
```lean-4
set_option trace.Compiler.init true
/--
trace: [Compiler.init] size: 4
def test x y : Bool :=
fun _y.1 _y.2 : Bool :=
cases x : Bool
| PUnit.unit =>
fun _f.3 a : Bool :=
return a;
let _x.4 := _f.3 _y.2;
return _x.4;
let _x.5 := _y.1 y;
return _x.5
-/
#guard_msgs in
def test (x : Unit) (y : Bool) : Bool :=
x.casesOn (fun a => a) y
```
which is now simplified to
```lean-4
set_option trace.Compiler.init true
/--
trace: [Compiler.init] size: 3
def test x y : Bool :=
cases x : Bool
| PUnit.unit =>
let a := y;
return a
-/
#guard_msgs in
def test (x : Unit) (y : Bool) : Bool :=
x.casesOn (fun a => a) y
```
This is especially relevant for #8309 because there `dite` is defined as
an over-applied `Bool.casesOn`.
This PR adds the option `doc.verso.module`. If set, it controls whether
module docstrings use Verso syntax. If not set, it defaults to the value
of the `doc.verso` option.
Closes#12070.
This PR fixes an issue on new NeoVim versions that would cause the
language server to display an error when using certain code actions.
(For some reason, NeoVim recently decided to diverge from VS Code in
terms of when it emits code action resolution requests, which means that
not setting the `data?` field won't preclude NeoVim from emitting a
request anymore, which in turn means that the server can't resolve the
code action.)
This PR implements preparatory work for #12179. It implements a new
feature in `isDefEq` to ensure it does not increase the transparency
level to `.default` when checking definitionally equality of implicit
arguments. This transparency level bump was introduced in Lean 3, but it
is not a performance issue and is affecting Mathlib. This PR adds the
new feature, but it is disabled by default.
This PR adds a default `Inhabited` instance to `Theorem` type.
The need to do so came up in #12296 , as `Theorem` is one of the entries
of the structure which is the key entry of `SimpleScopedEnvExtension`.
This PR fixes the PR release workflow which was failing due to the
deprecated `MATHLIB4_COMMENT_BOT` PAT being invalid.
**Error:** `jq: error (at <stdin>:4): Cannot index string with string
"name"` when fetching labels - the API returned an error response
instead of labels array because the PAT credentials were bad.
**Changes:**
- Generate a token from the `mathlib-lean-pr-testing` GitHub App (ID:
2785182) for posting comments to Lean PRs about mathlib compatibility
- Use `GITHUB_TOKEN` for read-only label fetching (no special identity
needed)
- Update the bot username check from `leanprover-community-bot` to
`mathlib-lean-pr-testing[bot]`
**Secrets added:** `MATHLIB_LEAN_PR_TESTING_APP_ID` and
`MATHLIB_LEAN_PR_TESTING_PRIVATE_KEY` have been added to the repository.
Fixes the CI failure at
https://github.com/leanprover/lean4/actions/runs/21705647318/job/62595966115🤖 Prepared with Claude Code
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This PR adds `String.Slice.Subslice`, which is an unbundled version of
`String.Slice`.
This type is of interest because it is the correct type for string
searching and splitting operations to land in.
This PR just adds the type with minimal API. Additional API and
subsequent refactoring of the searching and splitting API is left for
future PRs.
This PR reverses the relationship between the `ForwardPattern` and
`ToForwardSearcher` classes.
Previously, it was possible to derive `ForwardPattern` (i.e.,
`dropPrefix?`) from `ToForwardSearcher` (i.e., get an iterator of
`SearchStep (s)`). Now, we give the default instance in the other
direction: it is now possible to derive `ToForwardSearcher` from
`ForwardPattern`. Since it is usually much easier to provide
`ForwardPattern` than `ToForwardSearcher`, this means more shared code,
which pays off double since we will give a correctness proof for the
default implementation in an upcoming PR.
This PR also adds some string lemmas.
This PR adds theorems that directly state that div and mod form an
injective pair: if `a / n = b / n` and `a % n = b % n` then `a = b`.
These complement existing div/mod lemmas and are useful for extension
arguments.
Upstreaming from
https://github.com/leanprover-community/mathlib4/pull/34201🤖 Prepared with Claude Code
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This PR fixes the PR release workflow which is failing to create
`lean-pr-testing` branches due to the deprecated `MATHLIB4_BOT` PAT (see
https://github.com/leanprover/lean4/actions/runs/21698772126/job/62574742680).
The fix uses `actions/create-github-app-token@v2` to generate a token
from the `mathlib-nightly-testing` GitHub App (ID: 2784211) instead,
which has write access to both `leanprover-community/batteries` and
`leanprover-community/mathlib4-nightly-testing`.
Requires adding `MATHLIB_NIGHTLY_TESTING_APP_ID` and
`MATHLIB_NIGHTLY_TESTING_PRIVATE_KEY` secrets to leanprover/lean4
(done).
🤖 Prepared with Claude Code
This PR ensures `simp` does not "simplify" instances by default. The old
behavior can be retrieved by using `simp +instances`. This PR is similar
to #12195, but for `dsimp`.
The backward compatibility flag for `dsimp` also deactivates this new
feature.
```
set_option backward.dsimp.instances true
```
Applying `simp` (and `dsimp`) to instances creates non-standard
instances, and this creates all sorts of problems in Mathlib.
---------
Co-authored-by: Henrik Böving <hargonix@gmail.com>
Co-authored-by: Sebastian Graf <sgraf1337@gmail.com>
Co-authored-by: Kim Morrison <kim@tqft.net>
2026-02-05 04:53:46 +00:00
2748 changed files with 18774 additions and 5786 deletions
@@ -6,7 +6,7 @@ building Lean itself - which is needed to again build those parts. This cycle is
broken by using pre-built C files checked into the repository (which ultimately
go back to a point where the Lean compiler was not written in Lean) in place of
these Lean inputs and then compiling everything in multiple stages up to a fixed
point. The build directory is organized in these stages:
point. The build directory is organized into these stages:
```bash
stage0/
@@ -79,7 +79,7 @@ with the contents of `src/stdlib_flags.h`, bringing them back in sync.
NOTE: A full rebuild of stage 1 will only be triggered when the *committed* contents of `stage0/` are changed.
Thus if you change files in it manually instead of through `update-stage0-commit` (see below) or fetching updates from git, you either need to commit those changes first or run `make -C build/release clean-stdlib`.
The same is true for further stages except that a rebuild of them is retriggered on any committed change, not just to a specific directory.
Thus when debugging e.g. stage 2 failures, you can resume the build from these failures on but may want to explicitly call `clean-stdlib` to either observe changes from `.olean` files of modules that built successfully or to check that you did not break modules that built successfully at some prior point.
Thus when debugging e.g. stage 2 failures, you can resume the build from these failures on but you may want to explicitly call `clean-stdlib` to either observe changes from `.olean` files of modules that built successfully or to check that you did not break modules that built successfully at some prior point.
If you have write access to the lean4 repository, you can also manually
trigger that process, for example to be able to use new features in the compiler itself.
@@ -101,7 +101,7 @@ The script `script/rebase-stage0.sh` can be used for that.
The CI should prevent PRs with changes to stage0 (besides `stdlib_flags.h`)
from entering `master` through the (squashing!) merge queue, and label such PRs
with the `changes-stage0` label. Such PRs should have a cleanedup history,
with the `changes-stage0` label. Such PRs should have a cleaned-up history,
with separate stage0 update commits; then coordinate with the admins to merge
your PR using rebase merge, bypassing the merge queue.
@@ -6,10 +6,16 @@ Authors: Siddharth Bhat, Jeremy Avigad
module
prelude
publicimportInit.Data.Nat.Bitwise.Lemmas
publicimportInit.Data.Int.Bitwise.Basic
importallInit.Data.Int.Bitwise.Basic
publicimportInit.Data.Int.DivMod.Lemmas
publicimportInit.Data.Int.DivMod.Basic
importInit.ByCases
importInit.Data.Int.DivMod.Lemmas
importInit.Data.Int.Pow
importInit.Data.Nat.Bitwise.Lemmas
importInit.Data.Nat.Lemmas
importInit.Omega
importInit.RCases
publicsection
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.