This PR updates docstrings and function signatures in order to complete
the transition from `Iter.Partial` to `Iter.Total` (extrinsically
terminating by default). It also deprecates `allowNontermination` and
adds `Iter.Total.atIdxSlow?`.
This PR ensures `dsimp` does not "simplify" instances by default. The
old behavior can be retrieved by using
```
set_option backward.dsimp.instances true
```
Applying `dsimp` to instances creates non-standard instances, and this
creates all sorts of problems in Mathlib.
This modification is similar to
```
set_option backward.dsimp.proofs true
```
---------
Co-authored-by: Kim Morrison <kim@tqft.net>
Co-authored-by: Claude <noreply@anthropic.com>
This PR documents the available `changelog-*` labels and when to use
them in the project-specific CLAUDE.md instructions.
🤖 Prepared with Claude Code
Co-authored-by: Claude <noreply@anthropic.com>
This PR fixes `Init.Data.Dyadic.Instances` and `Init.Data.Dyadic.Inv`.
Previously, all declarations defined in boths file were private and not
exposed.
This PR fixes how we determine whether a function parameter is an
instance.
Previously, we relied on binder annotations (e.g., `[Ring A]` vs `{_ :
Ring A}`)
to make this determination. This is unreliable because users
legitimately use
`{..}` binders for class types when the instance is already available
from
context. For example:
```lean
structure OrdSet (α : Type) [Hashable α] [BEq α] where
...
def OrdSet.insert {_ : Hashable α} {_ : BEq α} (s : OrdSet α) (a : α) : OrdSet α :=
...
```
Here, `Hashable` and `BEq` are classes, but the `{..}` binder is
intentional, the
instances come from `OrdSet`'s parameters, so type class resolution is
unnecessary.
The fix checks the parameter's *type* using `isClass?` rather than its
syntax, and
caches this information in `FunInfo`. This affects several subsystems:
- **Discrimination trees**: instance parameters should not be indexed
even if marked with `{..}`
- **Congruence lemma generation**: instances require special treatment
- **`grind` canonicalizer**: must ensure canonical instances
**Potential regressions**: automation may now behave differently in
cases where it
previously misidentified instance parameters. For example, a rewrite
rule in `simp` that was
not firing due to incorrect indexing may now fire.
---------
Co-authored-by: Kim Morrison <kim@tqft.net>
Co-authored-by: Claude <noreply@anthropic.com>
Due to the way variable expansion and if interact in cmake, unquoted
variable expansions should essentially never be used inside if and may
lead to unexpected behavior. Also, quoted variable expansions can
usually be replaced by the unquoted variable name.
For more details, see this section in the cmake docs:
https://cmake.org/cmake/help/latest/command/if.html#variable-expansion
As one example of the kinds of issues that can occur with unquoted
variable expansions, consider this check from
`src/shell/CMakeLists.txt`, which tries to ensure that a test is only
run in non-WASM builds.
```cmake
if(NOT ${EMSCRIPTEN})
```
If the variable `EMSCRIPTEN` is empty or not defined (as is the case in
a non-WASM build), `${EMSCRIPTEN}` expands to 0 arguments, meaning the
check becomes
```cmake
if(NOT)
```
Since the `NOT` is unquoted, the if now tries to resolve it as a
variable. Since the variable `NOT` does not exist, the condition is
false and the test is never executed, even in non-WASM builds.
This PR provides the `Nat`/`Int` lemmas `x ≤ y * z ↔ (x + z - 1) / z ≤
y`, `x ≤ y * z ↔ (x + y - 1) / y ≤ z` and `x / z + y / z ≤ (x + y) / z`.
The PR is inspired by a `human-eval-lean` problem, the solution of which
required these lemmas.
This PR adds the `introSubstEq` MetaM tactic, as an optimization over
`intro h; subst h` that avoids introducing `h : a = b` if it can be
avoided,
which is the case when `b` can be reverted without reverting anything
else. Speeds up the generation of `injEq` theorem.
This PR removes the LCNF testing framework. Unfortunately it never got
used much and porting it to
the extended LCNF structure now would be a bit of effort that would
ultimately be in vain.
This PR fixes a bug in `System.Uri.fileUriToPath?` where it wouldn't use
the default Windows path separator in the path it produces.
It also adjusts the URI patching in the interactive test runner to be
more robust.
This PR adds `mkBackwardRuleFromExpr` to create backward rules from
expressions, complementing the existing `mkBackwardRuleFromDecl` which
only works with declaration names.
The new function enables creating backward rules from partially applied
terms. For example, `mkBackwardRuleFromExpr (mkApp (mkConst
``Exists.intro [1]) Nat.mkType)` creates a rule for `Exists.intro` with
the type parameter fixed to `Nat`, leaving only the witness and proof as
subgoals.
The `levelParams` parameter supports universe polymorphism: when
creating a rule like `Prod.mk Nat` that should work at multiple universe
levels, the caller specifies which level parameters remain polymorphic.
The pattern's universe variables are then instantiated appropriately at
each application site.
Also refactors `Pattern.lean` to share code between declaration-based
and expression-based pattern creation, extracting `mkPatternFromType`
and `mkEqPatternFromType` as common helpers.
This PR adds theorems showing the consistency between `find?` and the
various index-finding functions. The theorems establish bidirectional
relationships between finding elements and finding their indices.
**Forward direction** (find? in terms of index):
- `find?_eq_map_findFinIdx?_getElem`: `xs.find? p = (xs.findFinIdx?
p).map (xs[·])`
- `find?_eq_bind_findIdx?_getElem?`: `xs.find? p = (xs.findIdx? p).bind
(xs[·]?)`
- `find?_eq_getElem?_findIdx`: `xs.find? p = xs[xs.findIdx p]?`
**Reverse direction** (index in terms of find?):
- `findIdx?_eq_bind_find?_idxOf?`: `xs.findIdx? p = (xs.find? p).bind
(xs.idxOf?)`
- `findFinIdx?_eq_bind_find?_finIdxOf?`: `xs.findFinIdx? p = (xs.find?
p).bind (xs.finIdxOf?)`
- `findIdx_eq_getD_bind_find?_idxOf?`: `xs.findIdx p = ((xs.find?
p).bind (xs.idxOf?)).getD xs.length`
All theorems are provided for `List`, `Array`, and `Vector` (where
applicable).
Requested at
https://leanprover.zulipchat.com/#narrow/channel/113488-general/topic/show.20that.20Array.2Efind.3F.20and.20Array.2EfindFinIdx.3F.20consistent/near/567340199🤖 Prepared with Claude Code
Co-authored-by: Claude <noreply@anthropic.com>
This PR activates `getElem?_pos` more aggressively, triggered by `c[i]`.
- [x] depends on: #12176🤖 Prepared with Claude Code
---------
Co-authored-by: Claude <noreply@anthropic.com>
This PR fixes an issue where PR releases were not created when the test
suite failed, even though the build artifacts were available. The
workflow now runs whenever a PR's CI completes, regardless of
success/failure, and relies on the artifact verification step to ensure
the necessary build artifacts exist before proceeding.
This allows developers to get PR toolchains and test against Mathlib
even when the Lean test suite has failures, as long as the build jobs
succeeded.
🤖 Prepared with Claude Code
Co-authored-by: Claude <noreply@anthropic.com>
This PR fixes a bug where delayed E-match theorem instances could cause
uniqueId collisions in the instance tracking map.
The `uniqueId` for theorem instances is generated using `numInstances`,
but this counter was only bumped for immediately activated instances
(`.ready` case), not for delayed instances (`.next` case). This caused
ID collisions:
1. Theorem A matches, becomes delayed, gets `uniqueId = N`
2. Counter isn't bumped (stays at N)
3. Theorem B matches next, gets `uniqueId = N` (same!)
4. B's entry overwrites A's entry in `instanceMap`
5. A's tracking is lost
This manifested as `grind?` and `finish?` producing `instantiate approx`
(meaning "we couldn't determine which theorems to use") instead of
proper `instantiate only [...]` with specific theorem lists.
The fix bumps `numInstances` for delayed instances too, ensuring each
theorem instance gets a truly unique ID.
🤖 Prepared with Claude Code
Co-authored-by: Claude <noreply@anthropic.com>
This PR adds `prefix_map_iff_of_injective` and
`suffix_map_iff_of_injective` lemmas to Init.Data.List.Nat.Sublist.
These lemmas establish that if a function `f` is injective, then the
prefix and suffix relations are preserved under mapping (e.g., `l₁.map f
<+: l₂.map f ↔ l₁ <+: l₂`). These additions complement the existing
index-based lemmas in this file and allow for simpler structural proofs
without resorting to `take`, `drop`, or manual index manipulation.
This PR adds the function `Std.Iter.first?` and proves the specification
lemma `Std.Iter.first?_eq_match_step` if the iterator is productive.
The monadic variant on `Std.IterM` is also provided.
We use this new function to fix the default implementation for
`startsWith` and `dropPrefix` on `String` patterns, which used to fail
if the searcher returned a `skip` at the beginning. None of the patterns
we ship out of the box were affected by this, but user-defined patterns
were vulnerable.
---------
Co-authored-by: Paul Reichert <6992158+datokrat@users.noreply.github.com>
This PR adds regression tests that catch issues where structures/classes
with class-typed fields produce HEq goals in `congr` instead of handling
Prop fields automatically.
Both tests pass on v4.28.0-rc1 (before isInstance detection changes).
## Test 1: Structure extending classes (mirrors Mathlib's GroupTopology)
```lean
structure MyGroupTopology (α : Type) extends MyTopology α, IsContinuousMul α
theorem MyGroupTopology.toMyTopology_injective {α : Type} :
Function.Injective (MyGroupTopology.toMyTopology : MyGroupTopology α → MyTopology α) := by
intro f g h
cases f
cases g
congr
```
**Failure mode:** `⊢ toIsContinuousMul✝¹ ≍ toIsContinuousMul✝`
## Test 2: Class with explicit class-typed field (mirrors Mathlib's
PseudoEMetricSpace)
```lean
class MyMetricSpace (α : Type) extends MyDist α where
dist_self : ∀ x : α, dist x x = 0
toMyUniformity : MyUniformity α -- explicit class-typed field (NOT from extends)
uniformity_dist : toMyUniformity.uniformity (fun x y => dist x y = 0)
protected theorem MyMetricSpace.ext {α : Type} {m m' : MyMetricSpace α}
(h : m.toMyDist = m'.toMyDist) (hU : m.toMyUniformity = m'.toMyUniformity) : m = m' := by
cases m
cases m'
congr 1 <;> assumption
```
**Failure mode:** `⊢ dist_self✝¹ ≍ dist_self✝` and `⊢ uniformity_dist✝¹
≍ uniformity_dist✝`
## Context
These tests are related to #12172, which changes instance parameter
detection from binder-based to `isClass?`-based. That change can affect
how structure fields are classified in congruence lemma generation.
🤖 Prepared with Claude Code
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This PR clarifies the release notes title format in the release
checklist documentation.
**Changes:**
- Add explicit section explaining title format for -rc1, subsequent RCs,
and stable releases
- Make it clear that titles should include both the RC suffix AND the
date (e.g., "Lean 4.7.0-rc1 (2024-03-15)")
- Update example to use realistic date format instead of YYYY-MM-DD
- Clarify that only content is written for -rc1, subsequent releases
just update the title
This addresses confusion about whether RC release notes should include
the date in the title.
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This PR documents an issue encountered during the v4.28.0-rc1 release:
if release notes are merged to the reference-manual repository AFTER the
version tag is created, the deployed documentation won't include them.
The fix is to either:
1. Include release notes in the same PR as the toolchain bump (or merge
before tagging)
2. Regenerate the tag after merging release notes
🤖 Prepared with Claude Code
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This PR switches the PR release workflow from
`softprops/action-gh-release` to `gh release create`.
The `softprops/action-gh-release` action enumerates all releases to
check for existing ones, which fails when the repository has more than
10000 releases due to GitHub API pagination limits. The
`lean4-pr-releases` repository has accumulated over 10000 releases,
causing the PR release workflow to fail with:
```
Only the first 10000 results are available.
```
This is currently blocking all PR toolchain releases, including
https://github.com/leanprover/lean4/pull/12175.
🤖 Prepared with Claude Code
---------
Co-authored-by: Claude <noreply@anthropic.com>
This PR scopes the `simp` attribute on `FamilyOut.fam_eq` to the `Lake`
namespace. The lemma has a very permissive discrimination tree key
(`_`), so when `Lake.Util.Family` is transitively imported into
downstream projects, it causes `simp` to attempt this lemma on every
goal, leading to timeouts.
See
https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Lake.20.60FamilyOut.2Efam_eq.60.20leads.20to.20timeouts.3F🤖 Prepared with Claude Code
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Mac Malone <tydeu@hatpress.net>
This PR fixes a comment that said "implicit arguments" when the code
actually checks `isInstImplicit`, which is specifically for instance
implicit arguments (`[...]` binders), not all implicit arguments.
🤖 Prepared with Claude Code
Co-authored-by: Claude <noreply@anthropic.com>