Commit graph

39720 commits

Author SHA1 Message Date
Wojciech Różowski
7ca47aad7d
feat: add cbv at location syntax (#12773)
This PR adds `at` location syntax to the `cbv` tactic, matching the
interface of `simp at`. Previously `cbv` could only reduce the goal
target; now it supports `cbv at h`, `cbv at h |-`, and `cbv at *`.

`cbvGoal` is rewritten to use `Sym.preprocessMVar` followed by `cbvCore`
within a single `SymM` context, sharing the term table across all
hypotheses and the target. The old `cbvGoalCore` (which reduced one side
of an equation goal at a time) is replaced by a general approach that
reduces arbitrary goal types and hypothesis types, with special handling
for `True` targets and `False` hypotheses. `cbvDecideGoal` is updated to
use the extracted `cbvCore` as well.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:12:07 +00:00
Wojciech Różowski
1f04bf4fd1
feat: add simpDecideCbv simproc for cbv decide (#12766)
This PR adds a dedicated cbv simproc for `Decidable.decide` that
directly matches on `isTrue`/`isFalse` instances, producing simpler
proof terms and avoiding unnecessary unfolding through `Decidable.rec`.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 14:24:14 +00:00
Markus Himmel
03a5db34c7
feat: generalize String.Slice.Pos.cast (#12771)
This PR generalizes `String.Slice.Pos.cast`, which turns an `s.Pos` into
a `t.Pos`, to no longer require `s = t`, but merely `s.copy = t.copy`.

This is a breaking change, but one that is easy to adapt to, by
replacing `proof` with `congrArg Slice.copy proof` where required.
2026-03-03 09:23:51 +00:00
Kim Morrison
f4bbf748df
feat: add deriving noncomputable instance syntax (#12756)
This PR adds `deriving noncomputable instance Foo for Bar` syntax so
that delta-derived instances can be marked noncomputable. Previously,
when the underlying instance was noncomputable, `deriving instance`
would fail with an opaque async compilation error.

Now:
- `deriving noncomputable instance Foo for Bar` marks the generated
instance as noncomputable (using `addDecl` + `addNoncomputable` instead
of `addAndCompile`)
- `deriving instance Foo for Bar` pre-checks for noncomputable
dependencies and gives an actionable error with a "Try this:" suggestion
pointing to the noncomputable variant
- For handler-based deriving (inductives/structures), `noncomputable`
sets `isNoncomputable` on the scope

The `optDefDeriving` and `optDeriving` trailing parsers are updated with
`notSymbol "noncomputable"` to prevent them from stealing the parse of
`deriving noncomputable instance ...`.

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 06:42:41 +00:00
Mac Malone
46fe37290e
feat: lake: download artifacts on demand (#12634)
This PR enables Lake to download artifacts from a remote cache service
on demand as part of a `lake build`. It also refactors much of the cache
API to be more type safe.

The newly documented `lake cache add` command loads input-to-output
mappings from a file and stores them in the cache with optional
information about which cache service and what scope they come from.
With this information, Lake can now download artifacts on demand during
a `lake build`.

The `lake cache get` command has also changed its default behavior to
download just the input-to-outputs mapping and then lazily fetch
artifacts from Reservoir as part of a `lake build`. The original eager
behavior can be forced via the new `--download-arts` option.
2026-03-03 03:48:56 +00:00
Kim Morrison
dd710dd1bd
feat: use StateT.run instead of function application (#5121)
This PR using `StateT.run` rather than the "defeq abuse" of function
application. There remain many places where we still use function
application for `ReaderT`, but I've updated this in the touched files.

(To really solve this, we would make `StateT` irreducible, but that is
not happening here.)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 03:12:26 +00:00
Kim Morrison
9a841125e7
chore: add HACK banner to isNonTrivialRegular transparency check (#12769)
This PR adds a HACK comment to the transparency restriction in
`isNonTrivialRegular` (from
https://github.com/leanprover/lean4/pull/12650) so it's not forgotten.

🤖 Prepared with Claude Code

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 00:40:08 +00:00
Kim Morrison
2daaa50afb
chore: constructorNameAsVariable linter respects linter.all (#4966)
This PR ensures `linter.all` disables `constructorNameAsVariable`.

The issue was discovered by @eric-wieser while investigating a quote4
issue.

This seems like an easy mistake to make when setting up a new linter,
and perhaps we need a better structure to make it easy to do the right
thing.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 00:20:21 +00:00
Lean stage0 autoupdater
145a121048 chore: update stage0 2026-03-02 22:42:13 +00:00
Leonardo de Moura
584d92d302
refactor: replace isImplicitReducible with Meta.isInstance in shouldInline (#12759)
This PR replaces the `isImplicitReducible` check with `Meta.isInstance`
in the `shouldInline` function within `inlineCandidate?`.

At the base phase, we skip inlining instances tagged with
`[inline]`/`[always_inline]`/`[inline_if_reduce]` because their local
functions will be lambda lifted during the base phase. The goal is to
keep instance code compact so the lambda lifter can extract
cheap-to-inline declarations. Inlining instances prematurely expands the
code and creates extra work for the lambda lifter — producing many
additional lambda-lifted closures.

The previous check used `isImplicitReducible`, which does not capture
the original intent: some `instanceReducible` declarations are not
instances. `Meta.isInstance` correctly targets only actual type class
instances. Although `Meta.isInstance` depends on the scoped extension
state, this is safe because `shouldInline` runs during LCNF compilation
at `addDecl` time — any instance referenced in the code was resolved
during elaboration when the scope was active, and LCNF compilation
occurs before the scope changes.

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

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 21:49:46 +00:00
Wojciech Różowski
d66aaebca6
perf: simplify cbv ite/dite simprocs by reducing Decidable instance directly (#12677)
This PR changes the approach in `simpIteCbv` and `simpDIteCbv`, by
replacing call to `Decidable.decide`
with reducing and direct pattern matching on the `Decidable` instance
for `isTrue`/`isFalse`. This produces simpler proof terms.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 17:11:48 +00:00
Henrik Böving
4ac7ea4aab
perf: fixup BitVec.cpop termination proof performance (#12764) 2026-03-02 16:53:45 +00:00
Wojciech Różowski
6bebf9c529
feat: add short-circuit evaluation for Or and And in cbv (#12763)
This PR adds pre-pass simprocs `simpOr` and `simpAnd` to the `cbv`
tactic that evaluate only the left argument of `Or`/`And` first,
short-circuiting when the result is determined without evaluating the
right side. Previously, `cbv` processed `Or`/`And` via congruence, which
always evaluated both arguments. For expressions like `decide (m < n ∨
expensive)`, when `m < n` is true, the expensive right side is now
skipped entirely.

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

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 13:47:04 +00:00
Luisa Cicolini
df74c80973
feat: add bitblasting circuit for BitVec.cpop (#12433)
This PR adds a bitblasting circuit for `BitVec.cpop` with a
divide-and-conquer for a parallel-prefix-sum.

This is the [most efficient circuit we could
fine](https://docs.google.com/spreadsheets/d/1dJ5uUY4-eWIQmMjIui3H4U-wBxBxy-qYuqJZFZD1xvA/edit?usp=sharing),
after comparing with Kernighan's algorithm and with the intuitive
addition circuit.

---------

Co-authored-by: Henrik Böving <hargonix@gmail.com>
2026-03-02 13:38:04 +00:00
Paul Reichert
292b423a17
feat: injectivity lemmas for getElem(?) on List and Option (#12435)
This PR provides injectivity lemmas for `List.getElem`, `List.getElem?`,
`List.getElem!` and `List.getD` as well as for `Option`. Note: This
introduces a breaking change, changing the signature of
`Option.getElem?_inj`.
2026-03-02 09:44:45 +00:00
Kim Morrison
cda84702e9
doc: add guidance on waiting for CI/merges in release command (#12755)
This PR adds a section to the /release command explaining how to use `gh
pr checks --watch` to wait for CI or merges without polling.

🤖 Prepared with Claude Code

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 02:49:34 +00:00
Kim Morrison
ec565f3bf7
fix: use _fvar._ instead of _ for anonymous fvars (#12745)
This PR fixes `pp.fvars.anonymous` to display loose free variables as
`_fvar._` instead of `_` when the option is set to `false`. This was the
intended behavior in https://github.com/leanprover/lean4/pull/12688 but
the fix was committed locally and not pushed before that PR was merged.

🤖 Prepared with Claude Code

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 09:59:13 +00:00
Kim Morrison
feea8a7611
fix: use pull_request_target for label-triggered workflows (#12638)
This PR switches four lightweight workflows from `pull_request` to
`pull_request_target` to stop GitHub from requiring manual approval when
the
`mathlib-lean-pr-testing[bot]` app triggers label events (e.g. adding
`builds-mathlib`). Since the bot never lands commits on master, it is
perpetually treated as a "first-time contributor" and every
`pull_request`
event it triggers requires approval. `pull_request_target` events always
run
without approval because they execute trusted code from the base branch.

This is safe for all four workflows because none check out or execute
code
from the PR branch — they only read labels, PR body, and file lists from
the
event payload and API:

- `awaiting-mathlib.yml` — checks label combinations
- `awaiting-manual.yml` — checks label combinations
- `pr-body.yml` — checks PR body formatting
- `check-stdlib-flags.yml` — checks if stdlib_flags.h was modified via
API

Also adds explicit `permissions: pull-requests: read` to each workflow
as a
least-privilege hardening measure, since `pull_request_target` has
access to
secrets.

Addresses the issue reported by Sebastian:

https://lean-fro.zulipchat.com/#narrow/channel/398861-general/topic/mathlib.20pr-testing.20breakage.3F/near/575084348

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 19:20:56 +11:00
Kim Morrison
6d305096e5
chore: fix profiler shebang and add profiling skill (#12519)
This PR changes the shebang in `lean_profile.sh` from `#!/bin/bash` to
`#!/usr/bin/env bash` so the script works on NixOS and other systems
where bash is not at `/bin/bash`, and adds a Claude Code skill pointing
to the profiler documentation.

🤖 Prepared with Claude Code

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 07:09:33 +00:00
Kim Morrison
235b0eb987
feat: add Meta.synthInstance.apply trace class (#12699)
This PR gives the `generate` function's "apply @Foo to Goal" trace nodes
their own trace sub-class `Meta.synthInstance.apply` instead of sharing
the parent `Meta.synthInstance` class.

This allows metaprograms that walk synthesis traces to distinguish
instance application attempts from other synthesis nodes by checking
`td.cls` rather than string-matching on the header text.

The new class is registered with `inherited := true`, so `set_option
trace.Meta.synthInstance true` continues to show these nodes.

Motivated by mathlib's `#defeq_abuse` diagnostic tactic
(https://github.com/leanprover-community/mathlib4/pull/35750) which
currently checks `headerStr.contains "apply"` to identify these nodes.
See
https://leanprover.zulipchat.com/#narrow/channel/113488-general/topic/backward.2EisDefEq.2ErespectTransparency

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 07:06:56 +00:00
Kim Morrison
5dd8d570fd
feat: add pp.fvars.anonymous option (#12688)
This PR adds a `pp.fvars.anonymous` option (default `true`) that
controls the display of loose free variables (fvars not in the local
context).

- When `true` (default), loose fvars display their internal name like
`_fvar.42`
- When `false`, they display as `_fvar._`

This is analogous to `pp.mvars.anonymous` for metavariables. It's useful
for stabilizing output in `#guard_msgs` when messages contain fvar IDs
that vary between runs — for example, in diagnostic tools that report
`isDefEq` failures from trace output where the local context is not
available.

🤖 Prepared with Claude Code

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 06:43:14 +00:00
Kim Morrison
3ea59e15b8
fix: set implicitReducible on grandparent subobject projections (#12701)
This PR fixes a gap in how `@[implicit_reducible]` is assigned to parent
projections during structure elaboration.

When `class C extends P₁, P₂` has diamond inheritance, some ancestor
structures become constructor subobject fields even though they aren't
direct parents. For example, in `Monoid extends Semigroup, MulOneClass`,
`One` becomes a constructor subobject of `Monoid` — its field `one`
doesn't overlap with `Semigroup`'s fields, and `inSubobject?` is `none`
during `MulOneClass` flattening.

`mkProjections` creates the projection `Monoid.toOne` but defers
reducibility to `addParentInstances` (guarded by `if !instImplicit`).
However, `addParentInstances` only processes direct parents from the
`extends` clause. Grandparent subobject projections fall through the gap
and stay `semireducible`.

This causes defeq failures when `backward.isDefEq.respectTransparency`
is enabled (#12179): at `.instances` transparency, the semireducible
grandparent projection can't unfold, so two paths to the same ancestor
structure aren't recognized as definitionally equal.

Fix: before `addParentInstances`, iterate over all `.subobject` fields
and set `implicitReducible` on those whose parent is a class.

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 06:39:17 +00:00
Kim Morrison
d59f229b74
fix: mark levelZero, levelOne, and Level.ofNat as implicit_reducible (#12719)
This PR marks `levelZero` and `Level.ofNat` as `@[implicit_reducible]`
so that `Level.ofNat 0 =?= Level.zero` succeeds when the definitional
equality checker respects transparency annotations. Without this,
coercions between structures with implicit `Level` parameters fail, as
reported by @FLDutchmann on
[Zulip](https://leanprover.zulipchat.com/#narrow/channel/113488-general/topic/backward.2EisDefEq.2ErespectTransparency/near/576131374).

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 06:37:54 +00:00
Garmelon
a364595111
chore: fix ci after new linter was added (#12733)
The linter was running in parallel with other tests, which were creating
and deleting files. Since the linter was iterating over some files and
directories at the time, it crashed.
2026-02-28 03:05:07 +00:00
Garmelon
08ab8bf7c3
chore: fix ci for new test suite (#12704) 2026-02-27 23:25:37 +00:00
Lean stage0 autoupdater
54df5173d2 chore: update stage0 2026-02-27 21:05:46 +00:00
Garmelon
36ffba4b57
chore: ensure test names differ by more than just case (#12729)
These tests may lead to issues on case insensitive file systems.
2026-02-27 19:03:22 +00:00
Henrik Böving
2e9e5db408
feat: extract simple array literals as static initializers (#12724)
This PR implements support for extracting simple ground array literals
into statically initialized data.
2026-02-27 18:42:21 +00:00
Henrik Böving
81a5eb55d5
feat: boxed simple ground literal extraction (#12727)
This PR implements simple ground literal extraction for boxed scalar
values.
2026-02-27 16:15:14 +00:00
Markus Himmel
b4f768b67f
feat: lemmas about splitting the empty string/slice (#12725)
This PR shows that lawful searchers split the empty string to `[""]`.
2026-02-27 11:04:17 +00:00
Markus Himmel
9843794e3f
feat: lemmas for String.split by a character or character predicate (#12723)
This PR relates `String.split` to `List.splitOn` and `List.splitOnP`,
provided that we are splitting by a character or character predicate.

Also included: some more lemmas about `List.splitOn`, and a refactor of
the generic `split` verification to get rid of the awkward `SlicesFrom`
constuct.
2026-02-27 09:46:58 +00:00
Markus Himmel
9bd4dfb696
chore: prefer cons_cons over cons₂ in names (#12710)
This PR deprecated the handful of names in core involving the component
`cons₂` in favor of `cons_cons`.
2026-02-27 08:58:08 +00:00
Henrik Böving
b1db0d2798
perf: non quadratic closed term initialization for closed array literals (#12715)
This PR ensures the compiler extracts `Array`/`ByteArray`/`FloatArray`
literals as one big closed term to avoid quadratic overhead at closed
term initialization time.
2026-02-27 08:37:12 +00:00
Sebastian Graf
4cd7a85334
test: speed up Sym mvcgen by doing fewer redundant program matches (#12712)
This PR changes the spec lookup procedure in Sym-based mvcgen so that

1. Spec candidates are sorted first before being filtered
2. Instead of filtering the whole set of candidates using
`spec.pattern.match?`, we take the first match with the highest
priority.

The second point means we will do a lot fewer matches when the highest
priority spec matches immediately. In this case, the one match is still
partially redundant with the final application of the backward rule
application. It would be great if could somehow specialize the backward
rule after it has been created. Still, this yields some welcome
speedups. Before and after for each.

```
vcgen_add_sub_cancel:
goal_1000: 865 ms, 1 VCs by grind: 228 ms, kernel: 435 ms
goal_1000: 540 ms, 1 VCs by grind: 229 ms, kernel: 426 ms

vcgen_ping_pong:
goal_1000: 458 ms, 0 VCs, kernel: 431 ms
goal_1000: 454 ms, 0 VCs, kernel: 443 ms (unchanged, because there is only ever one candidate spec)

vcgen_deep_add_sub_cancel:
goal_1000: 986 ms, 1 VCs by grind: 234 ms, kernel: 735 ms
goal_1000: 728 ms, 1 VCs by grind: 231 ms, kernel: 708 ms

vcgen_reader_state:
goal_1000: 746 ms, 1 VCs by sorry: 1 ms, kernel: 803 ms
goal_1000: 525 ms, 1 VCs by sorry: 1 ms, kernel: 840 ms
```
2026-02-27 03:24:34 +00:00
Sebastian Graf
6cf1c4a1be
chore: simplify a proof in mvcgen test cases and remove duplicate (#12547) 2026-02-27 01:18:06 +00:00
Sebastian Graf
e7aa785822
chore: tighten a do match elaborator test case to prevent global defaulting (#12675)
This PR enshrines that the do `match` elaborator does not globally
default instances, in contrast to the term `match` elaborator.
2026-02-27 01:17:27 +00:00
Sebastian Graf
668f07039c
chore: do not use Sym.inferType in mvcgen if inputs are not shared (#12713) 2026-02-27 01:15:09 +00:00
Kyle Miller
005f6ae7cd
fix: let Meta.zetaReduce zeta reduce have expressions (#12695)
This PR fixes a bug in `Meta.zetaReduce` where `have` expressions were
not being zeta reduced. It also adds a feature where applications of
local functions are beta reduced, and another where zeta-delta reduction
can be disabled. These are all controllable by flags:
- `zetaDelta` (default: true) enables unfolding local definitions
- `zetaHave` (default: true) enables zeta reducing `have` expressions
- `beta` (default: true) enables beta reducing applications of local
definitions

Closes #10850
2026-02-27 00:37:52 +00:00
Henrik Böving
738688efee
chore: cleanup after closed term extraction by removing dead values (#12717) 2026-02-26 22:33:08 +00:00
Garmelon
adf3e5e661
chore: stop using cached namespace.so checkout (#12714)
The namespace cache volumes were running out of space and preventing CI
from running.
2026-02-26 17:18:52 +00:00
Sebastian Graf
38682c4d4a
fix: heartbeat limit in mvcgen due to withDefault rfl (#12696)
This PR fixes a test case reported by Alexander Bentkamp that runs into
a heartbeat limit due to daring use of `withDefault` `rfl` in `mvcgen`.
2026-02-26 16:40:42 +00:00
Sebastian Graf
f2438a1830
test: support postcondition VCs in Sym VCGen (#12711)
This PR adds support for generating and discharging postcondition VCs in
Sym-based `mvcgen`. It also adds a new benchmark case
`vcgen_ping_pong.lean` that tests this functionality. This benchmark
required a more diligent approach to maintain maximal sharing in goal
preprocessing. Goal preprocessing was subsequently merged into the main
VC generation function.
2026-02-26 16:34:15 +00:00
Markus Himmel
48c37f6588
feat: assorted string lemmas (#12709)
This PR adds various `String` lemmas that will be useful for deriving
high-level theorems about `String.split`.
2026-02-26 16:10:52 +00:00
Sebastian Graf
8273df0d0b
fix: quantify over α before ps in PostCond definitions (#12708)
This PR changes the order of implicit parameters `α` and `ps` such that
`α` consistently comes before `ps` in `PostCond.noThrow`,
`PostCond.mayThrow`, `PostCond.entails`, `PostCond.and`, `PostCond.imp`
and theorems.
2026-02-26 16:00:00 +00:00
Henrik Böving
f83a8b4cd5
refactor: port simple ground expr extraction from IR to LCNF (#12705)
This PR ports the simple ground expression extraction pass from IR to
LCNF.

I locally confirmed that this produces no diff between stage1/stage2 at
the C level (apart from the
changed compiler files) so this should essentially be binary equivalent.
2026-02-26 15:10:01 +00:00
Markus Himmel
fedfc22c53
feat: lemmas for String.intercalate (#12707)
This PR adds lemmas about `String.intercalate` and
`String.Slice.intercalate`.
2026-02-26 15:05:41 +00:00
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