Skip to content

fix: mark List.length as @[implicit_reducible]#12924

Merged
Kha merged 3 commits intomasterfrom
list_len_issue
Mar 18, 2026
Merged

fix: mark List.length as @[implicit_reducible]#12924
Kha merged 3 commits intomasterfrom
list_len_issue

Conversation

@leodemoura
Copy link
Copy Markdown
Member

This PR fixes a regression introduced in Lean 4.29.0-rc2 where simp no longer simplifies inside type class instance arguments due to the backward.isDefEq.respectTransparency change. This breaks proofs where a term like (a :: l).length appears both in the main expression and inside implicit instance arguments (e.g., determining a BitVec width).

The problem: After simp only [List.length_cons], the main expression has l.length + 1 but instances still have (a :: l).length. Since simp no longer simplifies inside instances, and isDefEq won't unfold List.length at the default transparency, subsequent lemma applications fail.

Reproducer (from Son Ho, reported by Sebastian Ullrich):

theorem BitVec.getElem!_eq_testBit_toNat {w : Nat} (x : BitVec w) (i : Nat) :
     x[i]! = x.toNat.testBit i := by sorry

example (l : List Nat) (a : Nat) (j : Nat) :
  (0#((a :: l).length))[j]! = (0#((a :: l).length)).toNat.testBit j := by
  simp only [List.length_cons]
  simp only [BitVec.getElem!_eq_testBit_toNat] -- works in 4.28.0-rc1, fails in 4.29.0-rc6

The fix: Mark List.length as @[implicit_reducible], allowing isDefEq to unfold it when checking implicit arguments. Several proofs that previously needed a trailing rfl after simp now close directly, since simp can see through List.length in more positions.

Longer term: The root cause is that GetElem carries complex proof obligations in its type class instances, making implicit arguments sensitive to definitional equality of collection sizes. We are considering a redesign with a noncomputable GetElemV variant based on Nonempty that avoids these casts entirely, but that is a larger change planned for a future release.

This PR fixes a regression introduced in Lean 4.29.0-rc2 where `simp` no longer
simplifies inside type class instance arguments due to the
`backward.isDefEq.respectTransparency` change. This breaks proofs where a term
like `(a :: l).length` appears both in the main expression and inside implicit
instance arguments (e.g., determining a `BitVec` width). After
`simp only [List.length_cons]`, the main expression has `l.length + 1` but
instances still have `(a :: l).length`, and `isDefEq` won't unfold `List.length`
to reconcile them.

Marking `List.length` as `@[implicit_reducible]` allows `isDefEq` to unfold it
when checking implicit arguments, restoring the previous behavior.

The root cause is that `GetElem` carries complex proof obligations in its type
class instances, making the implicit arguments sensitive to definitional equality.
We are considering a longer-term redesign with a noncomputable `GetElemV` variant
based on `Nonempty` that avoids these casts entirely, but that is a larger change
planned for a future release.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@leodemoura leodemoura requested a review from kim-em as a code owner March 15, 2026 01:25
leodemoura and others added 2 commits March 15, 2026 01:27
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions bot added the toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN label Mar 15, 2026
@leanprover-bot
Copy link
Copy Markdown
Collaborator

Reference manual CI status:

  • ❗ Reference manual CI can not be attempted yet, as the nightly-testing-2026-03-09 tag does not exist there yet. We will retry when you push more commits. If you rebase your branch onto nightly-with-manual, reference manual CI should run now. You can force reference manual CI using the force-manual-ci label. (2026-03-15 02:40:53)

mathlib-nightly-testing bot pushed a commit to leanprover-community/batteries that referenced this pull request Mar 15, 2026
@github-actions github-actions bot added the mathlib4-nightly-available A branch for this PR exists at leanprover-community/mathlib4-nightly-testing:lean-pr-testing-NNNN label Mar 15, 2026
mathlib-nightly-testing bot pushed a commit to leanprover-community/mathlib4-nightly-testing that referenced this pull request Mar 15, 2026
@mathlib-lean-pr-testing mathlib-lean-pr-testing bot added the breaks-mathlib This is not necessarily a blocker for merging: but there needs to be a plan label Mar 15, 2026
@mathlib-lean-pr-testing
Copy link
Copy Markdown

Mathlib CI status (docs):

kim-em added a commit to leanprover-community/batteries that referenced this pull request Mar 18, 2026
kim-em added a commit to leanprover-community/mathlib4-nightly-testing that referenced this pull request Mar 18, 2026
@mathlib-lean-pr-testing
Copy link
Copy Markdown

Mathlib CI status (docs):

@mathlib-lean-pr-testing
Copy link
Copy Markdown

Mathlib CI status (docs):

@Kha Kha changed the base branch from nightly-with-mathlib to master March 18, 2026 08:44
@Kha Kha added this pull request to the merge queue Mar 18, 2026
Merged via the queue into master with commit f0b367d Mar 18, 2026
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaks-mathlib This is not necessarily a blocker for merging: but there needs to be a plan changelog-library Library mathlib4-nightly-available A branch for this PR exists at leanprover-community/mathlib4-nightly-testing:lean-pr-testing-NNNN toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants