Commit graph

40297 commits

Author SHA1 Message Date
Henrik Böving
aa6fa1cf1a
chore: use the lean-llvm LLVM for benchmarking (#13634)
This PR makes radar use the LLVM that we actually ship to users (stored
at https://github.com/leanprover/lean-llvm). In doing so it also makes
the lake build compatible with lean-llvm, allowing us to do potential
release builds with lake in the future.
2026-05-05 14:26:08 +00:00
Garmelon
e47636cdca
chore: fix CI for PRs from external repos (#13643)
Those action runs don't have access to the READ_RUNNERS_TOKEN secret, so
they should just fall back to the namespace runner.

Also, this PR removes the permission checks again. They are failing for
some non-user authors (e.g. copilot) and could be removed anyways by a
malicious actor in a PR.
2026-05-05 13:38:54 +00:00
Sebastian Graf
42eb0385a5
test: bring Sym-based mvcgen' on par with mvcgen (#13578)
This PR brings the Sym-based `mvcgen'` to feature parity with `mvcgen`;
the only remaining gap is `+jp` (join-point handling).

The slight benchmark regressions are due to simplifying VCs out of
`SPred` form, hitting hardest on cases with linearly many VCs like
`PurePreCond`. The ~10% vcgen slowdown is worth it for the cleaner
user-visible VCs.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-05 13:17:20 +00:00
Henrik Böving
a43972c856
chore: don't use grind in HTTP (#13639) 2026-05-05 13:06:12 +00:00
Joachim Breitner
bd20c51ae4
feat: add trace.Meta.Tactic.simp.backwardDefEq (#13640)
This PR adds a trace event emitted whenever a `dsimp` (or rfl-only
`simp`) rewrite fires
because of a `[backward_defeq]`-tagged theorem (i.e., one that would not
have applied without `set_option backward.defeqAttrib.useBackward
true`).

Useful for finding where downstream code is silently relying on the
backwards escape hatch — a precursor to either re-tagging the lemma as
`[defeq]` or restructuring the proof so it works under the strict
defeq rules.
2026-05-05 13:02:27 +00:00
Eric Wieser
e4c0a5a511
fix: perform severity overrides before counting errors (#13589)
This PR ensures that the `lean --error=tag` flag actually sets a
non-zero exit code on promoted errors.

Closes #13588, fixing the feature introduced in #6362.
2026-05-05 09:31:50 +00:00
Eric Wieser
94a29d1952
fix: prevent undefined behavior without LEAN_MMAP (#13521)
This PR prevents undefined behavior in `readModuleDataParts #[]` on
configurations without `LEAN_MMAP`. Previously this would lead to
out-of-bounds indexing.
2026-05-05 07:42:20 +00:00
Eric Wieser
70098e432b
fix: handle interrupted reads (#13493)
This PR ensures that `import` gracefully processes `EINTR` errors from
the filesystem.

`read()` is allowed to return fewer bytes than requested, if it is
interrupted. If it is interrupted before returning any bytes, then it
returns `EINTR`. In either case, Lean should keep reading the file.
2026-05-05 07:41:52 +00:00
Eric Wieser
c9855f5dbf
fix: propagate memory errors in mpz.cpp (#13547)
This PR prevents silent allocation failures leading to memory corruption
when not using GMP.
2026-05-05 07:40:35 +00:00
Eric Wieser
a2c4b7305d
fix: indicate in readModuleDataParts if memory is exhausted (#13549)
This PR makes `readModuleDataParts` report a clearer error if there is
insufficient memory to load a module.

changelog-ignores-my-messages-unless-i-edit-the-description-afterwards
2026-05-05 07:38:46 +00:00
Leonardo de Moura
8ebd294673
fix: kernel projection panic in Sym.simp match reduction (#13635)
This PR fixes a `Sym.simp` panic ("unexpected kernel projection term
during simplification") that triggered when matcher iota-reduction
exposed kernel `Expr.proj` terms via struct-eta. For example, a `do`
block with a `for` loop whose state is a tuple, where `Sym.simp`
unfolds the equational lemma and then descends into a destructuring
match.
2026-05-05 03:20:20 +00:00
Garmelon
9e5c86eac9
chore: move more radar bench logic to this repo (#13633)
These commands were previously executed in the radar-bench-lean4
repository, but are now moved here for additional control.
2026-05-04 18:21:22 +00:00
Sebastian Ullrich
c8191c5e2c
refactor: align ScopedEnvExtension.exportEntry? with new PersistentEnvExtension.exportEntriesFn (#13628) 2026-05-04 15:35:59 +00:00
Garmelon
5f262d3b18
chore: update release tooling and docs (#13631) 2026-05-04 15:33:36 +00:00
Garmelon
666e8302c7
chore: use self-hosted actions runner for some runs (#13543) 2026-05-04 15:33:24 +00:00
Julia Markus Himmel
ba502f7027
chore: rename UInt8.ofNatTruncate to UInt8.ofNatClamp (#13627)
This PR renames `UInt8.ofNatTruncate` to `UInt8.ofNatClamp`.

The new name is more consistent with the rest of the library (e.g.,
`Int8.toNatClampNeg`) and also more clear. See also [#lean4 > Name of
UInt32.ofNatTruncate etc may be
wrong](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Name.20of.20UInt32.2EofNatTruncate.20etc.20may.20be.20wrong/with/591873604).

Historical note: during prehistoric times (in January 2024),
`UInt32.ofNatTruncate` (only the 32 bit version) was introduced for use
in the `simp` configuration. When I looked at the `UIntX` API more
properly later, I added the missing variants but didn't reconsider the
name.
2026-05-04 11:02:10 +00:00
Mac Malone
dae325700c
fix: lake: await needs before processing module headers (#13601)
This PR changes Lake's module import graph processing to await the
completion of any `needs` targets or other extra dependencies (such as
cloud releases). This both enables the `needs` targets to influence
header processing and prevents them from racing with said processing.

**Known Limitation:** This PR currently blocks on the `needs` targets
rather than running the import processing in a callback. This is done to
keep import processing simple and in a single thread. If this proves to
be a performance issue, this can be restructured in a future PR with a
more sophisticated refactor.

Closes #13598
2026-05-03 18:17:08 +00:00
Mac Malone
326f43aa3a
fix: lake: meta import transitive import artifacts (#13600)
This PR fixes a Lake issue where the IR for a `meta import`'s transitive
imports was not included in the import artifacts Lake provided to Lean
(e.g., via `--setup`). When using the Lake artifact cache, this could
produce "missing data file" errors due to absent IR.

Closes #13419

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
2026-05-03 17:44:46 +00:00
Leonardo de Moura
316c39ffe4
fix: grind congruence-table invariant for lazy ite branches (#13624)
This PR fixes a `grind` congruence-table invariant violation that could
panic
when an `ite` branch was internalized lazily (after the condition became
`True`
or `False`) and that branch's equivalence class was later merged with
another.

`Internalize.lean` has a special case for `ite` that internalizes only
the
condition; the `then`/`else` branches are skipped and only internalized
later
on demand by `propagateIte`. The on-demand path (`applyCongrFun`) called
`internalize` for the branch but never called `registerParent` to add
the
parent `ite` to the branch's parent set in the e-graph. Subsequent
merges of
the branch's equivalence class then skipped re-hashing the `ite` in the
congruence table, leaving an orphan entry whose `congr` chain no longer
matched
the table's representative.

The fix adds the explicit `registerParent e rhs` that the standard
`for arg in args` loop in `Internalize.lean` would have made for an
ordinary
application argument; we are simply mirroring that pattern lazily. The
same
helper is reused by `propagateDIte`, but with parent registration
disabled
(controlled by a new `ite : Bool` parameter): for `dite` the `rhs`
propagated
upwards is a *constructed* reduction (built via `mkApp` from `e`'s
children,
possibly post-`preprocess`), not a structural argument of `e`, so
registering
`e` as its parent would be incorrect. The lambda branches of a `dite`
are
already eagerly internalized as parents of `e` by `Internalize.lean`, so
this
case does not need the fix.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 17:27:54 +00:00
Leonardo de Moura
ee8acc14e2
fix: grind cast internalization order (#13625)
This PR fixes a `grind` internal error triggered when `cast` (or
`Eq.rec`, `Eq.ndrec`, `Eq.recOn`) is applied to an argument that has not
yet been internalized. `pushCastHEqs` was emitting `e ≍ a` before
internalizing the args of `e`, so the `rhs` of the heq had no enode and
the debug sanity check tripped. The call now runs after the args are
internalized.
2026-05-03 16:32:10 +00:00
Leonardo de Moura
1b23b051f3
fix: missing proof hints in grind propagators (#13623)
This PR fixes proof construction issues in the `grind` projection
propagators.
2026-05-03 14:51:03 +00:00
Leonardo de Moura
2d79ec2883
fix: another grind AC invariant (#13622)
This PR fixes another issue in the `grind` AC invariant checker.
2026-05-03 13:33:13 +00:00
Leonardo de Moura
fe3c7394fd
fix: grind AC invariant (#13614)
This PR fixes the invariant in `grind` AC. equations in the todo queue
are not fully simplified.
2026-05-03 02:19:51 +00:00
Leonardo de Moura
030397785c
fix: missing case in processLevel at SymM (#13612)
This PR improves the universe unifier used by `SymM`.
2026-05-02 17:52:43 +00:00
Leonardo de Moura
75e37def8c
fix: remove incorrect assertion at Sym/Simp/Have.lean (#13611)
This PR removes an incorrect assertion in the simproc used to simplify
`have`-expressions in `Sym.simp`.
2026-05-02 16:26:35 +00:00
Sebastian Ullrich
508a113242
feat: add .instances-transparency type-check diagnostics (#13368)
This PR adds infrastructure to help diagnose cases where tactics like
`unfold`
leave the goal in a state that is type-correct only at `.default`
transparency,
causing `rw`/`simp` to fail at `.instances` transparency.

Changes:
- Add a `transparency` parameter to `Meta.check` (defaults to `.all`)
- Add `withInstancesTypeCheckNote` which appends a
lazy note to tactic errors when the target is not type-correct at
`.instances`
- Wrap `rw`, `simp`, `dsimp`, and `simp_all` at the Elab level
- Add opt-in `linter.tacticCheckInstances` that proactively checks every
  tactic goal and reports semireducible defs that should be marked
`@[implicit_reducible]`, using diagnostic counter diffing between
`.default`
  and `.instances` checks
2026-05-02 12:17:51 +00:00
Sebastian Ullrich
b7ca76a96e
chore: refine PR description guidance in .claude/CLAUDE.md (#13597)
Keep it short and user-level in the first paragraph
2026-05-02 12:02:25 +00:00
Sebastian Ullrich
4b8e74b27a
chore: disable flaky test (#13603) 2026-05-02 11:58:17 +00:00
Sebastian Ullrich
06ac472859
feat: detect further sub-instances in wrapInstance (#13536)
This PR extends the procedure behind `inferInstanceAs`/`def ...
deriving` to continue recursion through the class graph even when a
(local) instance to wrap was found in order to re-use already-wrapped
instance of subclasses.
2026-05-02 11:55:04 +00:00
Sebastian Ullrich
c53c4b4d2e
fix: prevent private default instances from leaking into public scope (#13596)
This PR fixes private(ly imported) default instances from accidentally
being used in public signatures, leading to follow-up errors.

As reported at
https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Elaboration.20of.20heterogeneous.20mul.20with.20the.20module.20system
2026-05-02 07:53:44 +00:00
David Thrane Christiansen
659249a7df
fix: always fail on unsolved metavariables after Verso docstring elab (#13574)
This PR ensures consistent metavariable behavior between Verso
docstrings and Verso moduledocs by sharing more code between their
elaborators. It also improves the error message when a metavariable leak
is prevented.
2026-05-01 22:34:52 +00:00
Leonardo de Moura
53db221124
fix: disable model-based theory combination in grind derived tactics (#13593)
This PR disables model-based theory combination (`mbtc`) in `grind`'s
`NoopConfig`, which is the base configuration used by the derived
tactics `lia`, `linarith`, `cutsat`, `order`, and `ring`. Without this
fix, these tactics could engage in wasteful reasoning via theory
combination, causing them to run for a long time (or hit the
deterministic timeout) on problems they are not designed to solve. With
this fix, these tactics fail quickly on out-of-scope problems, as
expected.

Closes #13573.
2026-05-01 01:45:17 +00:00
Leonardo de Moura
a9946fe4ac
fix: case-split on arithmetic implications with And/Or antecedents (#13590)
This PR makes `lia` (and `grind`'s arithmetic case-split heuristic)
recognize
implications whose antecedent is an `And` or `Or` of arithmetic
predicates as
relevant case-split candidates. Previously, `Arith.isRelevantPred` only
matched
`Not`, `LE`, `LT`, `Eq`, and `Dvd`. With `splitImp := false` (the
default),
implications `p → q` are added as split candidates only when `p` is
arith-relevant, so a hypothesis like `(b ≤ e ∧ e < b + c → a ≤ e ∧ e < a
+ d)`
was never registered as a candidate. cutsat/lia would then find a
satisfying
assignment for the constraints it had been told about, but that
assignment
would not necessarily satisfy the original implication, yielding the bad
counterexample reported in #13575.

After this change, `isRelevantPred` recurses through `And` and `Or`
(returning
`true` if either operand is relevant), so the implication is split,
modus
ponens fires in the True branch, and cutsat/lia closes the False branch
via the
disjunction over negated atoms.

Closes #13575.
2026-04-30 23:15:34 +00:00
Wojciech Różowski
84f8c167c4
feat: script for finding deprecated options, modules and syntax (#13586)
This PR adds a script that imports the target modules and reads an
appropriate information from environment extensions about deprecated
modules, options and usage of deprecated syntax.
2026-04-30 17:30:43 +00:00
Leonardo de Moura
427e3bcdbc
fix: limit ring solver polynomial degree in grind (#13585)
This PR adds a `ringMaxDegree` configuration option (default `1024`)
that bounds the maximum degree of polynomials processed by the `grind`
ring solver. Equality constraints whose polynomial exceeds this
threshold are discarded (with an issue reported once per goal),
preventing pathological degree explosion on inputs such as `r ^ (2 ^ 250
- 1)`.

This PR also introduces `Poly.simpM?`, a monadic version of `Poly.simp?`
built on the existing safe arithmetic primitives (`mulMonM`, `combineM`,
`mulConstM`) in `Grind.Arith.CommRing.SafePoly`. The previous
reflection-oriented `Poly.simp?` in `Sym.Arith.Poly` lacked the abort
mechanisms needed during proof search, so the simplification path used
by `EqCnstr` now goes through the safe variant. A regression test
`tests/elab/grind_ring_degree_explosion.lean` ensures `grind` fails
quickly on high-degree problems.
2026-04-30 14:00:00 +00:00
Kyle Miller
19baa470e5
feat: MVarId.assertAfter fvar alias info, MVarId.replace mvar dependencies, specialize tactic using eta arguments (#13528)
This PR gives the `specialize` tactic the ability to instantiate
universal quantifiers other than the first using `specialize h (y := v)`
syntax. It also fixes an issue where `MVarId.assertAfter` did not record
variable alias information, and an issue where `MVarId.replace` and
`MVarId.replaceLocalDecl` did not take metavariables into account when
calculating dependencies. Additionally it fixes some uninstantiated
metavariables bugs, including one in the Infoview tactic state
hypothesis diff.

The `specialize` tactic now uses `Lean.MVarId.replace` to simplify the
implementation, and as a consequence it tries to keep the specialized
hypothesis close to its original spot in the local context.

Additional metaprogramming API:
- `Lean.Expr.getLambdaBody` to accompany `Lean.Expr.getNumHeadLambdas`
- `Lean.LocalContext.setType`, `Lean.MetavarContext.setFVarType`,
`Lean.MVarId.setFVarType`
- `Lean.MVarId.assertAfter'` to assert a new hypothesis as early as
possibly in the context where it is well-formed, as a frontend to
`Lean.MVarId.assertAfter`, which assumes the new hypothesis is
well-formed

Breaking change: metaprograms cannot assume that `MVarId`s change if
metavariables are assigned. For example, the `change` tactic will no
longer change `MVarId`s if the only effect is incidental metavariable
assignments.

Mathlib impact: this revealed many `dsimp`s that did nothing and could
be deleted.

Closes #9893
2026-04-30 10:36:29 +00:00
Sebastian Graf
ad5a3291dc
chore: switch Invariant helpers from abbrev to def + @[simp] (#13583)
This PR changes `Invariant`, `StringInvariant`, and
`StringSliceInvariant` from `abbrev` to `@[spec_invariant_type, simp,
grind =] def`, so that they remain visible as applications of a named
constant in proof states (where `SymM` does not unfold `def`s) and can
be detected as invariant types by `isSpecInvariantType`. The `@[simp,
grind =]` annotations ensure they still unfold on demand under `simp`
and `grind`.
2026-04-30 09:57:44 +00:00
Joachim Breitner
9efe4283e2
fix: propagate parent cancel token to parallel tactic subtasks (#13428)
This PR fixes parallel tactic combinators (`attempt_all_par`,
`first_par`) leaking their subtasks when the server cancels elaboration
on re-elaboration. Subtasks spawned via `CoreM.asTask` (and its
`MetaM`/`TermElabM`/`TacticM` variants) get a fresh `IO.CancelToken`,
which previously had no link to the parent token; `cancelRec` would set
the command-level token but the children kept running.

The fix is one line in `CoreM.asTask`: when a parent token is in scope,
register `cancelToken.set` as an `onSet` callback on the parent.
Server-level cancellation now flows down to every parallel subtask, and
`Core.checkInterrupted` inside the child sees the token set as expected.

Fixes #13300.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-30 09:22:33 +00:00
Sebastian Graf
906d9cf848
feat: add SPred and PostCond entailment lemmas (#13582)
This PR adds several entailment-related lemmas to `Std.Do.SPred` and
`Std.Do.PostCond`, intended for goal-decomposition during program
verification proof automation.

- `SPred.down_pure_nil` and `SPred.apply_pure_cons` (existing `rfl`
lemmas) become `@[simp, grind =]`. Drops the now-redundant `pure_cons`
argument from `simp` in `conjunction_apply`.
- New `SPred.entails_nil_intro` and `SPred.entails_nil_pure_intro`:
introduction forms for `entails` at `SPred []`, mirroring the existing
`entails_cons_intro`.
- New `SPred.down_pure_intro`: derive `(pure φ).down` from `φ`.
- New `SPred.apply_pure_cons_entails_l`/`_r`: peel a state argument from
`pure (σ::σs) φ s` on either side of `⊢ₛ`.
- New `Std.Do.ExceptConds.entails.pure`: closes any `⊢ₑ` goal at
`PostShape.pure`, where `ExceptConds.entails` reduces to `True`.
2026-04-30 06:30:49 +00:00
Wojciech Różowski
2b5d154a4c
feat: upstream unnecessarySeqFocus linter (#13540)
This PR upstreams `unnecessarySeqFocus` linter from batteries to core
lean as a "clippy" linter - i.e. one that is disabled by default and
executed by `lake lint --clippy`.

---------

Co-authored-by: Mac Malone <tydeu@hatpress.net>
Co-authored-by: Thomas R. Murrills <68410468+thorimur@users.noreply.github.com>
2026-04-29 14:51:10 +00:00
Sebastian Graf
e6f44eeeec
test: regression tests for do issues fixed by the new elaborator (#13541)
This PR adds regression tests for `do`-notation issues that the new
elaborator fixes:

* `tests/elab/doNotation7.lean` collects reproducers for #2663, #2676,
#3126, #5607, #6426, and #8119.
* `tests/elab/12229.lean` covers the `logInfo` and `Std.TreeMap`
reproducers from #12229.
2026-04-29 14:37:23 +00:00
Wojciech Różowski
2ba4c55a84
feat: upstream dupNamespace environment linter (#13538)
This PR upstreams `dupNamespace` linter from batteries to work with new
core environment linting framework, as a "clippy" linter - i.e. one that
is not enabled by default.

Stacked on top of #13513.

---------

Co-authored-by: Mac Malone <tydeu@hatpress.net>
Co-authored-by: Thomas R. Murrills <68410468+thorimur@users.noreply.github.com>
2026-04-29 12:50:40 +00:00
Leonardo de Moura
897e556d90
feat: add E-matching diagnostics to grind (#13558)
This PR adds the option `grind.ematch.diagnostics`, which tracks how
E-matching theorem instances depend on each other. When enabled, `grind`
records, for every new theorem instance, the set of previous instances
whose generated terms participated in the match. This produces a
hyper-graph `{thm_1, ..., thm_n} => thm` describing the provenance of
each instantiation.

The hyper-graph is stored in `Grind.Result` so downstream tooling can
inspect it. The trace class `trace.grind.ematch.diagnostics.compact`
prints a compact textual view of the hyper-graph, restricted to
constant-name origins. Example output:

```
  [grind.ematch.diagnostics.compact] ️ instances
    [inst] [] => th1
    [inst] [th1] => th3
    [inst] [th1] => th2
    [inst] [th2, th3] => th4
    [inst] [th4] => th5
```

The implementation stores an `ematchDiagSource` field on each `ENode`
and threads a `withEmatchDiagSource` reader through fact assertion so
that newly internalized terms inherit the origin of the instance that
produced them. During E-matching, `Choice` collects the sources of every
matched argument, and the resulting set becomes the predecessor set of
the new instance.
2026-04-29 12:17:55 +00:00
Vladimir Gladshtein
10b2efba51
feat: new foundations for mvcgen tactic (#12965)
This PR Introduces new foundations for reasoning about monadic Lean
code. Eventually we will port `mvcgen` on top of these new foundations,
to make the framework more general and robust.

Key issues, new metatheory is supposed to solve are
- It gives more flexibility over what an assertion language for
pre-/post-conditions of monadic Hoare triples can be. In particular, any
`CompleteLattice` might become a pre-/post-condtions language, not only
`SPred`. It potentially gives an opportunity to reason about
probabilistic monads, where assertion language are distributions. This
also simplifies the metatheory of monadic Hoare triples, as it does not
require defining the notion of `SPred`, and allows users to work in a
fairly common interface of `CompleteLattice`
- It splits the post-conditions of Hoare triples/ WPs into two: (1)
`post` for post-conditions on terminating paths and (2) `epost` for
post-conditions on abrupt paths. Current foundations always bundle them
into a pair, which inevitably leads to constructing and eliminating such
pairs everywhere in the code.
- It relaxes some conditions that the current foundations require for
instantiating `WPMonad` type class. In particular we do not require `wp`
to distribute over `bind` any more. Instead, we require just `wp x (fun
x => wp (f x) post epost) epost ⊑ wp (x >>= f) post epost`, i.e. the
distributed `wp` must only imply the non-distributed one (and not
necessarily vice versa). With this we can define `WPMonad` for
Separation Logic, where `wp` only distributes over `bind` on
local-footprint computations.
- It solves some universe polymorphism issues. As now universe levels of
assertion languages are independent of universe levels in the monad, one
can define `WPMonad Id.{u} Prop EPost⟨⟩`, which means that for arbitrary
level `Id` the language for pre-/post-conditions is going to be just
`Prop` and the language for post-conditions on abrupt exits is idle.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-29 11:28:30 +00:00
Joachim Breitner
b763ab8a5e
refactor: keep IO.CancelToken task private, resolve promise before setting flag (#13569)
This PR addresses two review points on `IO.CancelToken`:

* `set` now resolves the underlying promise *before* writing the `Bool`
  fast-path flag, so observing `isSet = true` implies any synchronously
chained `onSet` callback has already run. The previous order (flag
first,
then resolve) was a subtle footgun: code seeing `isSet = true` could not
  rely on the cancellation task having fired.
* The underlying promise and the task it produces are kept private. The
prior `task : Task (Option Unit)` accessor is removed; consumers should
use `onSet` to react to cancellation. A comment on the structure records
  that re-exposing the task in the future requires re-auditing the order
  in `set` for races between the promise and the `Bool` flag.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 11:12:54 +00:00
Kim Morrison
0a6c31520b
doc: note TransparencyMode and ReducibilityStatus constructors are not in unfolding order (#13564)
This PR adds source-level comments noting that the constructors of
`Lean.Meta.TransparencyMode` and `Lean.ReducibilityStatus` are not laid
out in the unfolding-amount order suggested by their docstrings, and
that reordering them induces a non-trivial bootstrap problem.

Also rewrites a stale comment in `Lean.Meta.Basic` that listed the
hierarchy in descending order without `.none`.

🤖 Prepared with Claude Code

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 04:22:55 +00:00
Mac Malone
9df737d492
fix: lake: race condition in monitor queue (#13559)
This PR fixes a race condition in the Lake build monitor's draining of
the job queue.

Previously, the monitor drained the registered-jobs queue before
checking task states. A finished job in that scan may have registered
new jobs in its body just before terminating. Those jobs landed in the
queue after the drain, so when no other unfinished jobs remained the
monitor exited without ever observing them. If one of the missed jobs
errors, this could produce an "uncaught top-level build failure" message
alongside "Build completed successfully".

To fix this, the monitor loop is restructured so the queue is drained
*after* task states are scanned, with an additional drain before the
loop terminates. `drainQueue` and `scanJobs` are split out from `poll`,
and `Monitor.main` performs an initial drain to capture any jobs
registered before the monitor starts iterating. Finishing jobs cannot
register further work once their state transitions, so a single
post-scan drain is sufficient to close the window.

🤖 Prepared with Claude Code
2026-04-28 22:44:48 +00:00
Leonardo de Moura
5852865c92
fix: beta reduction in grind must respect generation threshold (#13560)
This PR fixes a bug in `propagateBetaEqs` (in
`Lean.Meta.Tactic.Grind.Beta`)
where new equalities/terms introduced by beta reduction were added to
the goal
without checking the generation threshold. The generation of the new
fact
is the maximum generation of the lambda, the function `f`, and its
arguments, plus one. Without the threshold check, beta reduction can
cascade indefinitely on self-similar lambdas such as
`(fun b => f (b + 1)) = fun b => f b`, which kept producing
`f n = f (n + 1)` for every `n`. The fix aggregates argument generations
before the threshold check and bails out when the resulting generation
reaches `maxGeneration`.
2026-04-28 21:51:14 +00:00
Joachim Breitner
c36b0fb165
refactor: make CancelToken Promise-based (#13303)
This PR moves `IO.CancelToken` from `Init.System.IO` to its own file
`Init.System.CancelToken`, backed by `IO.Promise Unit` instead of
`IO.Ref Bool`. This enables non-polling cancellation propagation: the
token's underlying promise can be used directly with `IO.waitAny`, and
callbacks can be registered to fire when cancellation is requested.

The structure carries both the promise *and* a plain `IO.Ref Bool` flag,
set in lockstep by `set`. `isSet` reads the flag directly (used on hot
paths like `Core.checkInterrupted`); `task`/`onSet` go through the
promise. The avoids a ~0.4% regression that a pure-promise
representation introduced.

API additions:

- `CancelToken.task : Task (Option Unit)`. Returns the underlying
promise's `result?` task directly — the same task object on every call,
so further `Task.map`/`BaseIO.bindTask` dependencies can be safely
attached. Resolves with `some ()` when `set` is called, or `none` if the
token is dropped without ever being set.
- `CancelToken.onSet : BaseIO Unit → BaseIO Unit`. Registers a callback
that runs synchronously on the cancelling thread when `set` is called
(or immediately if the token is already set). Implemented via
`BaseIO.chainTask` on `result?`, so no fresh `Task.map` per call and no
GC hazard.

Runtime cleanup:

- Add `LEAN_TASK_STATE_{WAITING,RUNNING,FINISHED}` constants in `lean.h`
matching `IO.TaskState`.
- Factor `lean::promise_is_resolved` inline in `object.h`, replacing
three open-coded `lean_io_get_task_state_core(...) == 2` checks (in
`interrupt.cpp`, `uv/timer.cpp`, `uv/signal.cpp`).
- Drop the manual `inc_ref(g_cancel_tk)` in `check_interrupted`; the
token is owned by the enclosing `scope_cancel_tk` for the duration of
the call (documented).
- Replace the bare `lean_always_assert(g_task_manager)` in
`lean_promise_new` with an explicit `lean_internal_panic` carrying a
message that names `Promise.new`, identifies the typical trigger
(`initialize` blocks, transitively via `IO.CancelToken.new`), and
recommends lazy construction. Without this, users got an opaque "LEAN
ASSERTION VIOLATION ... Condition: g_task_manager" with no actionable
hint.

Behavioural notes documented inline:

- `new` cannot be called from `initialize` blocks (task manager not
running yet); construct lazily.
- `task` documents the dropped-promise case (`none`) and steers callers
to `onSet` for callback chaining.

A consumer of `onSet` for parent → child cancel-token propagation in
parallel tactic combinators is in #13428 (fixes #13300).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-28 21:50:54 +00:00
Eric Wieser
6819c805b9
fix: propagate memory errors when allocating for libuv (#13546)
This PR prevents memory exhaustion turning into segfaults when using
Lean functions which call into libuv

`malloc` can return `NULL`, in which case this code would previously go
on to dereference a null pointer.
Instead, it now returns a suitable `IO.Error`.

Calling `lean_internal_panic_out_of_memory` would also be an option
here, since the adjacent `lean_promise_new` calls would fail in this
way.
2026-04-28 15:29:25 +00:00