Commit graph

39674 commits

Author SHA1 Message Date
Markus Himmel
a91fb93eee
feat: simproc for String.singleton (#12706)
This PR adds a dsimproc which evaluates `String.singleton ' '` to `" "`.
2026-02-26 14:41:56 +00:00
Sebastian Graf
b3b4867d6c
feat: add two unfolding theorems to Std.Do (#12697)
This PR adds two new unfolding theorems to Std.Do: `PostCond.entails.mk`
and `Triple.of_entails_wp`.
2026-02-26 14:31:07 +00:00
Markus Himmel
1e4894b431
feat: upstream List.splitOn(P) (#12702)
This PR upstreams `List.splitOn` and `List.splitOnP` from
Batteries/mathlib.

The function `splitOnP.go` is factored out to `splitOnPPrepend`, because
it is useful to state induction hypotheses in terms of
`splitOnPPrepend`.
2026-02-26 13:45:34 +00:00
Lean stage0 autoupdater
846420daba chore: update stage0 2026-02-26 10:20:57 +00:00
Henrik Böving
d88ac25bd1
feat: non exponential codegen for reset-reuse (#12665)
This PR ports the expand reset/reuse pass from IR to LCNF. In addition
it prevents exponential code generation unlike the old one. This results
in a ~15% decrease in binary size and slight speedups across the board.

The change also removes the "is this reset actually used" syntactic
approximation as the previous passes guarantee (at the moment) that all
uses are in the continuation and will thus be caught by this.
2026-02-26 09:35:45 +00:00
Lean stage0 autoupdater
805060c0a8 chore: update stage0 2026-02-26 08:58:17 +00:00
Sebastian Ullrich
b1a991eee0
perf: separate meta and non-meta initializers (#12016)
This PR enables the module system, in cooperation with the linker, to
separate meta and non-meta code in native binaries. In particular, this
ensures tactics merely used in proofs do not make it into the final
binary. A simple example using `meta import Lean` has its binary size
reduced from 130MB to 1.7MB.

# Breaking change

`importModules (loadExts := true)` must now be preceded by
`enableInitializersExecution`. This was always the case for correct
importing but is now enforced and checked eagerly.
2026-02-26 08:05:19 +00:00
Sebastian Ullrich
65a0c61806
chore: idbg refinements (#12691) 2026-02-26 07:49:47 +00:00
Wojciech Różowski
d4b560ec4a
test: add cbv tests adapted from LNSym (#12694)
This PR adds two `decide_cbv` stress tests extracted from LNSym (ARMv8
symbolic
simulator, Apache 2.0). `cbv_aes.lean` tests a full AES-128 encryption
on large
bitvector computations. `cbv_arm_ldst.lean` tests ARMv8 load/store
instruction
decoding and execution with nested pattern matching over bitvectors.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 17:08:24 +00:00
Wojciech Różowski
7390024170
test: add cbv test for Collatz conjecture verification (#12692)
This PR adds a `cbv` tactic test based on a minimized example extracted
from verifying the Collatz conjecture for small numbers, suggested by
Bhavik Mehta (@b-mehta).

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Bhavik Mehta <bhavikmehta8@gmail.com>
2026-02-25 17:05:51 +00:00
Henrik Böving
805012fb84
chore: revert "perf: improve over-applied cases in ToLCNF (#12284)" (#12693)
This PR reverts commit 9b7a8eb7c8. After
some more contemplation on
the implications of these changes I think this is not the direction we
want to move into.
2026-02-25 15:23:24 +00:00
Garmelon
dc760cf54a
chore: fail build on non-make generators (#12690)
At the moment, the build relies on make and will fail with other cmake
generators. This explicit check (as suggested by @LecrisUT in
https://github.com/leanprover/lean4/pull/12577#discussion_r2832295132)
should help prevent confusion like in #12575.
2026-02-25 13:59:40 +00:00
Garmelon
08eb78a5b2
chore: switch to new test/bench suite (#12590)
This PR sets up the new integrated test/bench suite. It then migrates
all benchmarks and some related tests to the new suite. There's also
some documentation and some linting.

For now, a lot of the old tests are left alone so this PR doesn't become
even larger than it already is. Eventually, all tests should be migrated
to the new suite though so there isn't a confusing mix of two systems.
2026-02-25 13:51:53 +00:00
Kyle Miller
bd0c6a42c8
fix: copied 11940 fix for structure command (#12680)
This PR fixes an issue where `mutual public structure` would have a
private constructor. The fix copies the fix from #11940.

Closes #10067. Also recloses duplicate issue #11116 (its test case is
added to the test suite).
2026-02-25 13:50:04 +00:00
Paul Reichert
c86f82161a
feat: upstream List/Array/Vector lemmas from human-eval-lean (#12405)
This PR adds several useful lemmas for `List`, `Array` and `Vector`
whenever they were missing, improving API coverage and consistency among
these types.
- `size_singleton`/`sum_singleton`/`sum_push`
-
`foldlM_toArray`/`foldlM_toList`/`foldl_toArray`/`foldl_toList`/`foldrM_toArray`/`foldrM_toList`/`foldr_toList`
- `toArray_toList`
- `foldl_eq_apply_foldr`/`foldr_eq_apply_foldl`, `foldr_eq_foldl`:
relates `foldl` and `foldr` for associative operations with identity
- `sum_eq_foldl`: relates sum to `foldl` for associative operations with
identity
- `Perm.pairwise_iff`/`Perm.pairwise`: pairwise properties are preserved
under permutations of arrays
2026-02-25 12:50:31 +00:00
Paul Reichert
b548cf38b6
feat: enable partial termination proofs about WellFounded.extrinsicFix (#12430)
This PR provides `WellFounded.partialExtrinsicFix`, which makes it
possible to implement and verify partially terminating functions, safely
building on top of the seemingly less general `extrinsicFix` (which is
now called `totalExtrinsicFix`). A proof of termination is only
necessary in order to formally verify the behavior of
`partialExtrinsicFix`.
2026-02-25 12:43:39 +00:00
Henrik Böving
e96d969d59
feat: support for del, isShared, oset and setTag (#12687)
This PR implements the LCNF instructions required for the expand reset
reuse pass.
2026-02-25 10:43:15 +00:00
Sebastian Ullrich
532310313f
feat: lake shake --only (#12682)
This PR extends `lake shake` with a flag for minimizing only a specific
module
2026-02-25 10:24:50 +00:00
Marc Huisinga
168c125cf5
chore: relative lean-toolchains (#12652)
This PR changes all `lean-toolchain` to use relative toolchain paths
instead of `lean4` and `lean4-stage0` identifiers, which removes the
need for manually linking toolchains via Elan.

After this PR, at least Elan 4.2.0 and 0.0.224 of the Lean VS Code
extension will be needed to edit core.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 10:23:35 +00:00
Sebastian Ullrich
54be382b2f chore: fix core after rebootstrap 2026-02-25 11:40:02 +01:00
Sebastian Ullrich
fa31b285df chore: update stage0 2026-02-25 11:40:02 +01:00
Sebastian Ullrich
1fd9adc693 fix: update-stage0 under the Lake cache 2026-02-25 11:40:02 +01:00
Sebastian Ullrich
423671a6c0 feat: strengthen evalConst meta check 2026-02-25 11:40:02 +01:00
Markus Himmel
1e0bfe931f
feat: more lemmas about String.Slice.Pos.ofSlice(From|To)? (#12685)
This PR adds some missing material about transferring positions across
the subslicing operations `slice`, `sliceFrom`, `sliceTo`.
2026-02-25 09:39:59 +00:00
Henrik Böving
1bf43863e6
fix: better LCNF pretty printing (#12684) 2026-02-25 09:30:23 +00:00
Markus Himmel
87ec768a50
fix: ensure that tail-recursive List.flatten is used everywhere (#12678)
This PR marks `List.flatten`, `List.flatMap`, `List.intercalate` as
noncomputable to ensure that their `csimp` variants are used everywhere.

We also mark `List.flatMapM` as noncomputable and provide a
tail-recursive implementation, and mark `List.utf8Encode` as
noncomputable, which only exists for specification purposes anyway (at
this point).

Closes #12676.
2026-02-25 06:24:15 +00:00
Kyle Miller
de65af8318
feat: overriding binder kinds of parameters in inductive constructors (#12603)
This PR adds a feature where `inductive` constructors can override the
binder kinds of the type's parameters, like in #9480 for `structure`.
For example, it's possible to make `x` explicit in the constructor
`Eq.refl`, rather than implicit:
```lean
inductive Eq {α : Type u} (x : α) : α → Prop where
  | refl (x) : Eq x x
```
In the Prelude, this is currently accomplished by taking advantage of
auto-promotion of indices to parameters.

**Breaking change.** Inductive types with a constructor that starts with
typeless binders may need to be rewritten, e.g. changing `(x)` to `(x :
_)` if there is a `variable` with that name or if it is meant to shadow
one of the inductive type's parameters.
2026-02-25 02:30:12 +00:00
Kyle Miller
c032af2f51
fix: make tactic .. at * save info contexts (#12607)
This PR fixes an issue where `withLocation` wasn't saving the info
context, which meant that tactics that use `at *` location syntax and do
term elaboration would save infotrees but revert the metacontext,
leading to Infoview messages like "Error updating: Error fetching goals:
Rpc error: InternalError: unknown metavariable" if the tactic failed at
some locations but succeeded at others.

Closes #10898
2026-02-25 01:59:50 +00:00
Kyle Miller
48a715993d
fix: pretty printing of constants should consider accessibility of names (#12654)
This PR fixes two aspects of pretty printing of private names.
1. Name unresolution. Now private names are not special cased: the
private prefix is stripped off and the `_root_` prefix is added, then it
tries resolving all suffixes of the result. This is sufficient to handle
imported private names in the new module system. (Additionally,
unresolution takes macro scopes into account now.)
2. Delaboration. Inaccessible private names use a deterministic
algorithm to convert private prefixes into macro scopes. The effect is
that the same private name appearing in multiple times in the same
delaborated expression will now have the same `✝` suffix each time. It
used to use fresh macro scopes per occurrence.

Note: There is currently a small hack to support pretty printing in the
compiler's trace messages, which print constants that do not exist (e.g.
`obj`, `tobj`, and auxiliary definitions being compiled). Even though
these names are inaccessible (for the stronger reason that they don't
exist), we make sure that the pretty printer won't add macro scopes. It
also does some analysis of private names to see if the private names are
for the current module.

Closes #10771, closes #10772, and closes #10773
2026-02-25 00:01:19 +00:00
Wojciech Różowski
f31f50836d
fix: withNamespace now correctly calls popScopes after running (#12647)
This PR adds the missing `popScopes` call to `withNamespace`, which
previously
only dropped scopes from the elaborator's `Command.State` but did not
pop the
environment's `ScopedEnvExtension` state stacks. This caused scoped
syntax
declarations to leak keywords outside their namespace when
`withNamespace` had
been called.

Closes #12630

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 15:24:58 +00:00
Lean stage0 autoupdater
c1ab1668b2 chore: update stage0 2026-02-24 15:19:57 +00:00
Sebastian Graf
7517f768f9
feat: lightweight dependent match motive for do match (#12673)
This PR allows for a leightweight version of dependent `match` in the
new `do` elaborator: discriminant types get abstracted over previous
discriminants. The match result type and the local context still are not
considered for abstraction. For example, if both `i : Nat` and `h : i <
len` are discrminants, then if an alternative matches `i` with `0`, we
also have `h : 0 < len`:

```lean
example {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (as : Array α) (b : β) (f : (a : α) → a ∈ as → β → m (ForInStep β)) : m β :=
  let rec loop (i : Nat) (h : i ≤ as.size) (b : β) : m β := do
    match i, h with
    | 0,   _ => pure b
    | i+1, h =>
      have h' : i < as.size            := Nat.lt_of_lt_of_le (Nat.lt_succ_self i) h
      have : as.size - 1 < as.size     := Nat.sub_lt (Nat.zero_lt_of_lt h') (by decide)
      have : as.size - 1 - i < as.size := Nat.lt_of_le_of_lt (Nat.sub_le (as.size - 1) i) this
      match (← f as[as.size - 1 - i] (Array.getElem_mem this) b) with
      | ForInStep.done b  => pure b
      | ForInStep.yield b => loop i (Nat.le_of_lt h') b
  loop as.size (Nat.le_refl _) b
```

This feature turns out to be enough to save quite a few adaptations
(6/16) during bootstrep.
2026-02-24 14:29:29 +00:00
Sebastian Graf
96cd6909ea
doc: fix comment referring to elabElem instead of elabDoElem (#12674) 2026-02-24 14:23:58 +00:00
Sebastian Graf
bb8d8da1af
test: add benchmark vcgen_reader_state (#12671)
This PR adds the benchmark vcgen_reader_state that is a variant of
vcgen_add_sub_cancel that takes the value to subtract from a `ReaderT`
layer. Measurements:
```
goal_100: 201 ms, 1 VCs by sorry: 0 ms, kernel: 52 ms
goal_500: 382 ms, 1 VCs by sorry: 0 ms, kernel: 327 ms
goal_1000: 674 ms, 1 VCs by sorry: 1 ms, kernel: 741 ms
```
Which suggests it scales linearly. The generated VC triggers superlinear
behavior in `grind`, though, hence it is discharged by `sorry`.
2026-02-24 13:19:15 +00:00
Sebastian Graf
8916246be5
test: speed up vcgen_get_throw_set.lean by partially evaluating specs (#12670)
This PR speeds up the vcgen_get_throw_set benchmark by a factor of 4 by
partially evaluating specs.
2026-02-24 13:10:42 +00:00
Wojciech Różowski
65f112a165
chore: rename prime filter benchmark and fix the merge sort benchmark (#12669)
This PR renames the "Eratosthenes' sieve" benchmark description to
"prime filter" in the speedcenter config (following the discussion in
https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/sieve.20of.20Eratosthenes.20benchmark/with/575310824),
and adds the missing `#eval runBenchmarks` call to the merge sort
benchmark so it actually executes.
2026-02-24 10:57:47 +00:00
Markus Himmel
75b083d20a
chore: API to prepare for String.split API (#12668)
This PR adds lemmas about string positions and patterns that will be
useful for providing high-level API lemmas for `String.split` and
friends.
2026-02-24 10:03:00 +00:00
Sebastian Ullrich
c595413fcc
test: robustify but also CI-disable idbg test for now (#12667) 2026-02-24 09:19:53 +00:00
Kyle Miller
cd7f55b6c9
feat: pp.mdata (#12606)
This PR adds the pretty printer option `pp.mdata`, which causes the
pretty printer to annotate terms with any metadata that is present. For
example,
```lean
set_option pp.mdata true
/-- info: [mdata noindex:true] 2 : Nat -/
#guard_msgs in #check no_index 2
```
The `[mdata ...] e` syntax is only for pretty printing.

Thanks to @Rob23oba for an initial version.

Closes #10929
2026-02-24 04:30:26 +00:00
Kyle Miller
673d1a038c
feat: clean up binder annotations inside of let rec definitions (#12608)
This PR continues #9674, cleaning up binder annotations inside the
bodies of `let rec` and `where` definitions.

Closes #11025
2026-02-24 04:24:47 +00:00
Lean stage0 autoupdater
66ce282364 chore: update stage0 2026-02-24 00:40:29 +00:00
Sebastian Graf
cdbed919ec
fix: preserve TermInfo for do-match discriminant variables (#12666)
This PR fixes spurious unused variable warnings for variables used in
non-atomic match discriminants in `do` notation. For example, in `match
Json.parse s >>= fromJson? with`, the variable `s` would be reported as
unused.

The root cause is that `expandNonAtomicDiscrs?` eagerly elaborates the
discriminant via `Term.elabTerm`, which creates TermInfo for variable
references. The result is then passed to `elabDoElem` for further
elaboration. When the match elaboration is postponed (e.g. because the
discriminant type contains an mvar from `fromJson?`), the result is a
postponed synthetic mvar. The `withTermInfoContext'` wrapper in
`elabDoElemFns` checks `isTacticOrPostponedHole?` on this result,
detects a postponed mvar, and replaces the info subtree with a `hole`
node — discarding all the TermInfo that was accumulated during
discriminant elaboration.

The fix applies `mkSaveInfoAnnotation` to the result, which prevents
`isTacticOrPostponedHole?` from recognizing it as a hole. This is the
same mechanism that `elabLetMVar` uses to preserve info trees when the
body is a metavariable.

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

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 23:54:17 +00:00
Sebastian Ullrich
6d86c8372a
perf: shake Lean.Elab.Idbg (#12664) 2026-02-23 21:59:55 +00:00
Lean stage0 autoupdater
5c23579f93 chore: update stage0 2026-02-23 20:33:27 +00:00
Sebastian Ullrich
d0f8eb7bd6
fix: @[nospecialize] is never template-like (#12663)
This PR avoids false-positive error messages on specialization
restrictions under the module system when the declaration is explicitly
marked as not specializable. It could also provide some minor public
size and rebuild savings.
2026-02-23 20:00:36 +00:00
Sebastian Graf
65e5053008
fix: add TermInfo for mut vars in ControlStack.stateT.runInBase (#12661)
This PR fixes false-positive "unused variable" warnings for mutable
variables reassigned inside `try`/`catch` blocks with the new do
elaborator.

The root cause was that `ControlStack.stateT.runInBase` packed mutable
variables into a state tuple without calling `Term.addTermInfo'`, so the
unused variable linter could not see that the variables were used. The
fix mirrors how the `for` loop elaborator handles the same pattern in
`useLoopMutVars`.

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

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 19:21:40 +00:00
Sebastian Ullrich
8f80881c2f
feat: idbg interactive debug expression evaluator (#12648)
This PR adds the experimental `idbg e`, a new do-element (and term)
syntax for live debugging between the language server and a running
compiled Lean program.

When placed in a `do` block, `idbg` captures all local variables in
scope and expression `e`, then:

- **In the language server**: starts a TCP server on localhost waiting
for the running program to
connect; the editor will mark this part of the program as "in progress"
during this wait but that
  will not block `lake build` of the project.
- **In the compiled program**: on first execution of the `idbg` call
site, connects to the server,
receives the expression, compiles and evaluates it using the program's
actual runtime values, and
  sends the `repr` result back.

The result is displayed as an info diagnostic on the `idbg` keyword. The
expression `e` can be
edited while the program is running - each edit triggers re-elaboration
of `e`, a new TCP exchange,
and an updated result. This makes `idbg` a live REPL for inspecting and
experimenting with
program state at a specific point in execution. Only when `idbg` is
inserted, moved, or removed does
the program need to be recompiled and restarted.

# Known Limitations

* The program will poll for the server for up to 10 minutes and needs to
be killed manually
  otherwise.
* Use of multiple `idbg` at once untested, likely too much overhead from
overlapping imports without
  further changes.
* `LEAN_PATH` must be properly set up so compiled program can import its
origin module.
* Untested on Windows and macOS.
2026-02-23 17:22:44 +00:00
Kim Morrison
ed0fd1e933
perf: restrict nontrivial class projection classification to reducible transparency (#12650)
This PR fixes a performance regression introduced by enabling
`backward.whnf.reducibleClassField`
(https://github.com/leanprover/lean4/pull/12538). The
`isNonTrivialRegular` function in `ExprDefEq` was classifying class
projections as nontrivial at all transparency levels, but the extra
`.instances` reduction in `unfoldDefault` that motivates this
classification only applies at `.reducible` transparency. At higher
transparency levels, the nontrivial classification caused unnecessary
heuristic comparison attempts in `isDefEqDelta` that cascaded through
BitVec reductions, causing elaboration of `Lean.Data.Json.Parser` to
double from ~3.6G to ~7.2G instructions.

The fix restricts the nontrivial classification to `.reducible`
transparency only, matching the scope of `unfoldDefault`'s extra
reduction behavior.

🤖 Prepared with Claude Code

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 15:10:45 +00:00
Markus Himmel
a4d1560aa7
feat: additional lemmas about min/minOn on single elements and lists (#12651)
This PR adds some missing lemmas about `min`, `minOn`, `List.min`,
`List.minOn`.
2026-02-23 14:25:46 +00:00
Henrik Böving
e16e2b2ffa
refactor: use Code.forM more (#12649) 2026-02-23 14:06:28 +00:00