Lean 4.29.0 (2026-03-27)
For this release, 453 changes landed. In addition to the 112 feature additions and 107 fixes listed below there were 30 refactoring changes, 21 documentation improvements, 29 performance improvements, 26 improvements to the test suite and 115 other changes.
Highlights
Violetta Sim has helpfully written the release highlights from 4.16 through 4.29, and the Lean developers gratefully acknowledge her contributions.
Performance Improvements
#12082 and #12044 reduce startup time by storing closed terms directly in the binary, where possible, and initializing the remaining ones lazily instead of at startup.
#12406 significantly
reduces the memory consumed by LRAT proof checking in bv_decide.
New Extensible do Elaborator
#12459 adds a new,
extensible do elaborator. Users can opt into the new elaborator by
unsetting the option backward.do.legacy.
New elaborators for the builtin doElem syntax category can be
registered with attribute doElem_elab. For new syntax, additionally
a control info handler must be registered with attribute
doElem_control_info that specifies whether the new syntax returns
early, breaks, continues and which mut vars it reassigns.
Do elaborators have type
TSyntax `doElem β DoElemCont β DoElabM Expr, where DoElabM is
essentially TermElabM and the DoElemCont represents how the rest
of the do block is to be elaborated. Consult the docstrings for more
details.
Breaking Changes:
-
The syntax for
let pat := rhs | otherwiseand similar now scope over thedoSeqthat follows. Furthermore,otherwiseand the sequence that follows are nowdoSeqIndentedin order not to steal syntax from record syntax.
Breaking Changes when opting into the new do elaborator by unsetting
backward.do.legacy:
-
donotation now always requiresPure. -
do matchis now always non-dependent. There isdo match (dependent := true)that expands to a term match as a workaround for some dependent uses.
mvcgen: Specifications in the Local Context
#12395 adds mvcgen support for specifications in the local context. Example:
import Std.Tactic.Do
open Std.Do
set_option mvcgen.warning false
def foo (x : Id Nat β Id Nat) : Id Nat := do
let rβ β x (pure 42)
let rβ β x (pure 26)
pure (rβ + rβ)
theorem foo_spec
(x : Id Nat β Id Nat)
(x_spec : β (k : Id Nat) (_ : β¦βTrueββ¦ k β¦βr => βr % 2 = 0ββ¦), β¦βTrueββ¦ x k β¦βr => βr % 2 = 0ββ¦) :
β¦βTrueββ¦ foo x β¦βr => βr % 2 = 0ββ¦ := by
mvcgen [foo, x_spec] <;> grind
def bar (k : Id Nat) : Id Nat := do
let r β k
if r > 30 then return 12 else return r
example : β¦βTrueββ¦ foo bar β¦βr => βr % 2 = 0ββ¦ := by
mvcgen [foo_spec, bar] -- unfold `bar` and automatically apply the spec for the higher-order argument `k`
grind: Higher-Order Miller Pattern Support in E-matching
#12483 adds support
for higher-order Miller patterns in grind's e-matching engine.
Previously, lambda arguments in e-matching patterns were always
treated as dontCare, meaning they could not contribute to matching
or bind pattern variables. This was a significant limitation for
theorems where lambda arguments carry essential structure, such as
List.foldl, List.foldrM, or any combinator that takes a function
argument.
With this change, when a pattern argument is a lambda whose body
satisfies the Miller pattern condition β i.e., pattern variables
are applied only to distinct lambda-bound variables β the lambda is
preserved as an ho[...] pattern. At instantiation time, these
higher-order patterns are matched via isDefEq after all first-order
pattern variables have been assigned by the E-graph.
Example
@[grind =] theorem applyFlip_spec (f : Nat β Nat β Nat) (a b : Nat)
: applyFlip (fun x y => f y x) a b = f b a := sorry
The pattern applyFlip ho[fun x => fun y => #2 y x] #1 #0 captures
the lambda argument structurally: #2 (the pattern variable for f)
is applied to distinct lambda-bound variables y and x. When
grind encounters applyFlip (fun x y => Nat.add y x) 3 4, it binds
f := Nat.add via isDefEq and fires the rewrite.
One Axiom per Native Computation
#12217 implements
RFC #12216: native
computation (native_decide, bv_decide) is represented in the logic
as one axiom per computation, asserting the equality that was obtained
from the native computation. #print axiom will no longer show
Lean.trustCompiler, but rather the auto-generated names of these
axioms (with, for example, ._native.bv_decide. in the name). See the
RFC for more information.
More Reliable Universe Level Inference in inductive/structure Commands
#12514 improves
universe level inference for the inductive and structure commands
to be more reliable and to produce better error messages. See the PR
description for more information.
Breaking change. Universe level metavariables present only in constructor fields are no longer promoted to be universe level parameters: use explicit universe level parameters. This promotion was inconsistently done depending on whether the inductive type's universe level had a metavariable, and also it caused confusion for users, since these universe levels are not constrained by the type former's parameters.
Breaking change. Now recursive types do not count as βobvious
Prop candidatesβ. Use an explicit Prop type former annotation on
recursive inductive predicates.
Simpler noncomputable Semantics
#12028 gives a
simpler semantics to noncomputable, improving predictability as well
as preparing codegen to be moved into a separate build step without
breaking immediate generation of error messages.
Specifically, noncomputable is now needed whenever an axiom or
another noncomputable def is used by a def except for the following
special cases:
-
uses inside proofs, types, type formers, and constructor arguments corresponding to (fixed) inductive parameters are ignored
-
uses of functions marked
@[extern]/@[implemented_by]/@[csimp]are ignored -
for applications of a function marked
@[macro_inline], noncomputability of the inlining is instead inspected
Breaking change: After this change, more noncomputable
annotations than before may be required in exchange for improved
future stability.
Changes to Instance and Reducibility Handling
v4.29.0 brings a significant and breaking change to the handling of reducibility settings.
We address a longstanding problem: prior to v4.29.0, the isDefEq algorithm would bump the
transparency level up to .default (i.e. become willing to unfold default transparency definitions)
when comparing implicit arguments.
This was a serious problem, causing both immediate unpredictable performance problems in
isDefEq, and hiding many places where definitional abuse was occurring in downstream libraries.
In order to ensure scalability, and address these definitional abuse problems, we have made the quite disruptive change, in #12179, of removing this transparency level bump as the default path.
The changes to the transparency bump in comparing implicit arguments can be controlled in two ways:
-
Definitions can be tagged with the new
@[implicit_reducible]attribute. This is intermediate between@[reducible]and@[semireducible](i.e. the default setting), in that the definition is mostly treated as semireducible, except whenisDefEqis processing implicit arguments or match discriminants. See #12247 and #12567. -
The option
set_option backward.isDefEq.respectTransparency falserestores the previous behaviour prior tov4.29.0(equivalently, all semireducible definitions are treated asimplicit_reducible). As a backward compatibility option, this may eventually be removed, but given how disruptive this change is we anticipate leaving the option available for the medium term.
As a consequence of these changes to transparency handling, existing definitional abuse problems in downstream libraries now surface in places
where previously they didn't. To help address these problems, which primarily, but not exclusively,
are caused by incorrectly implemented typeclass instances, we have made changes in #12897
to inferInstanceAs and the default deriving handler.
These ensure that instances created using them do not leak the definition of the types involved,
when the instances are reduced at less than semireducible transparency.
inferInstanceAs Ξ± synthesizes an instance of type Ξ± but now adjusts it to conform to the
expected type Ξ², which must be inferable from context.
Example:
def D := Nat instance : Inhabited D := inferInstanceAs (Inhabited Nat)
The adjustment will make sure that the resulting instance will not leak the RHS Nat when
reduced at transparency levels below semireducible, i.e. where D would not be unfolded either.
More specifically, given the source type (the argument) and target type (the expected type),
inferInstanceAs synthesizes an instance for the source type and then unfolds and rewraps its
components (fields, nested instances) as necessary to make them compatible with the target type. The
individual steps are represented by the following options, which all default to enabled and can be
disabled to help with porting:
-
backward.inferInstanceAs.wrap: master switch for instance adjustment in bothinferInstanceAsand the default deriving handler -
backward.inferInstanceAs.wrap.reuseSubInstances: reuse existing instances for the target type for sub-instance fields to avoid non-defeq instance diamonds -
backward.inferInstanceAs.wrap.instances: wrap non-reducible instances in auxiliary definitions -
backward.inferInstanceAs.wrap.data: wrap data fields in auxiliary definitions (proof fields are always wrapped)
If you just need to synthesize an instance without transporting between types, use inferInstance
instead, potentially with a type annotation for the expected type.
A third significant change in v4.29.0 is that simp and dsimp no longer process typeclass instances.
This behaviour was producing non-standard instances, and causing problems in Mathlib.
See #12244 and #12195.
The old behavior can be restored with
set_option backward.dsimp.instances true
or simp +instances for simp. Our experience so far, however, is that this is not often needed.
Finally we have fixed in #12172 a problem with how
we determine whether a function parameter is an instance, which has follow-on effects in several algorithms that depend on this classification.
This may cause 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.
Migration guide
Any projects wanting to postpone dealing with the adaptations required by the changes to transparency level bumps can
simply use set_option backward.isDefEq.respectTransparency false.
This can be set on a project-wide level in your lakefile.toml:
[leanOptions] backward.isDefEq.respectTransparency = false
However we encourage you to instead localize the option in the files that need it,
or even on individual declarations using set_option backward.isDefEq.respectTransparency false in ....
This makes it easier to start identifying the definitional abuse problems in your code.
If your project is downstream of Mathlib, you may find the following two scripts useful:
-
scripts/add_set_option.py(available in.lake/packages/mathlib/scripts/add_set_option.pyif you have Mathlib as a dependency) which tries compiling your project, and automatically wrapping any failing declaration withset_option backward.isDefEq.respectTransparency false in ..., in those cases where doing so resolves the failure. -
scripts/rm_set_option.py, which compiles your project and identifies all occurrences ofset_option backward.isDefEq.respectTransparency false in ...which can be removed without causing a failure (in that same declaration). This may happen because of earlier changes which resolve the definitional abuse problem.
These scripts can also be copied out of Mathlib and run on any project.
Again, when downstream of Mathlib you may also use the experimental #defeq_abuse in ... command,
which attempts to identify and explain, or at least give clues to, the underlying definitional abuse problem that
may explain why a declaration currently needs set_option backward.isDefEq.respectTransparency false in ....
We encourage users to report problems with this command on the Zulip,
and we hope that as this diagnostic command stabilizes we will be able to make it available as part of a future Lean toolchain.
You are encouraged to review the construction of instances for all default transparency type synonyms in your project.
Where possible, you should use the deriving handler, or the new inferInstanceAs elaborator,
rather than writing term mode constructions which require unfolding the type synonym in order to typecheck.
The inferInstanceAs command now requires an expected type.
If you encounter errors where inferInstanceAs now gives an error because an expected type was not provided,
you may find that you should simply be using inferInstance instead.
Universe Levels as Output Parameters
#12423 adds the
attribute @[univ_out_params] for specifying which universe levels
should be treated as output parameters. By default, any universe level
that does not occur in any input parameter is considered an output
parameter.
Library Highlights
This release includes a new string search infrastructure, using a polymorphic pattern system that works uniformly over characters, predicates, and strings. See:
-
#12333 adds the basic typeclasses that will be used in the verification of our string searching infrastructure.
-
#12424 gives a proof of
LawfulToForwardSearcherModelforSlicepatterns, which amounts to proving that our implementation of KMP is correct.
There are also various additions to the library, including:
-
#11938 introduces projected minima and maxima, also known as βargmin/argmaxβ, for lists under the names
List.minOnandList.maxOn. It also introducesList.minIdxOnandList.maxIdxOn, which return the index of the minimal or maximal element. -
#11994 provides more lemmas about sums of lists/arrays/vectors, especially sums of
NatorIntlists/arrays/vectors. -
#12363 introduces iterators for vectors via
Vector.iterandVector.iterM, together with the usual lemmas. -
#12452 upstreams
List.scanl,List.scanrand their lemmas from batteries into the standard library.
New Features in Lake
-
#12203 changes artifact transfer from the local cache to prefer hard links over copies, with a fallback to copying when hard linking fails (e.g., on a different filesystem). Cache artifacts are now marked read-only to prevent accidental corruption via hard-linked paths.
-
#12444 adds the Lake CLI command
lake cache clean, which deletes the Lake cache directory. -
#12490 adds a system-wide Lake configuration file and uses it to configure the remote cache services used by
lake cache.
Language
-
#11963 activates
getElem?_posmore aggressively, triggered byc[i]. -
#12028 gives a simpler semantics to
noncomputable, improving predictability as well as preparing codegen to be moved into a separate build step without breaking immediate generation of error messages. -
#12110 fixes a SIGFPE crash on
x86_64when evaluating(ISize.minValue / -1 : ISize), filling an omission from #11624. -
#12159 makes Std.Do's
postmacro universe polymorphic by expanding toPUnit.unitinstead of(). -
#12160 removes calls to
checkthat we expect to pass under normal circumstances. This may be re-added later guarded by adebugoption. -
#12164 uses the
.injtheorem in the proof of one direction of the.injEqtheorem. -
#12179 ensures
isDefEqdoes not increase the transparency mode to.defaultwhen checking whether implicit arguments are definitionally equal. The previous behavior was creating scalability problems in Mathlib. That said, this is a very disruptive change. The previous behavior can be restored using the commandset_option backward.isDefEq.respectTransparency false
-
#12184 ensures that the
mspectactic does not assign synthetic opaque MVars occurring in the goal, just like theapplytactic. -
#12190 adds the
introSubstEqMetaM tactic, as an optimization overintro h; subst hthat avoids introducingh : a = bif it can be avoided, which is the case whenbcan be reverted without reverting anything else. Speeds up the generation ofinjEqtheorem. -
#12217 implements RFC #12216: native computation (
native_decide,bv_decide) is represented in the logic as one axiom per computation, asserting the equality that was obtained from the native computation.#print axiomwill no longer showLean.trustCompiler, but rather the auto-generated names of these axioms (with, for example,._native.bv_decide.in the name). See the RFC for more information. -
#12219 fixes a unification issue that appeared in
Lean.Meta.MkIffOfInductivePropmachinery that was upstreamed from Mathlib. Inside oftoInductive, wrong free variables were passed, which made it impossible to perform a unification in certain cases. -
#12236 adds
orElsecombinator to simprocs ofSym.Simp. -
#12243 fixes #12240, where
deriving Ordfailed withUnknown identifier aβ. -
#12247 adds the new transparency setting
@[instance_reducible]. We used to check whether a declaration hadinstancereducibility by using theisInstancepredicate. However, this was not a robust solution because:-
We have scoped instances, and
isInstancereturnstrueonly if the scope is active.
-
-
#12263 implements the second part of #12247.
-
#12269 refines upon #12106, by setting the
isRecursiveenv extension after adding the declaration, but before processing attributes likemacro_inlinethat want to look at the flag. Fixes #12268. -
#12283 introduces
cbv_opaqueattribute that allows one to mark definitions not to be unfolded by thecbvtactic. -
#12285 implements a cache for the positions of class universe level parameters that only appear in output parameter types.
-
#12286 ensures the type resolution cache properly caches results for type classe containing output parameters.
-
#12324 adds a default
Inhabitedinstance toTheoremtype. -
#12325 adds a warning to any
defof class type that does not also declare an appropriate reducibility. -
#12329 adds the option
doc.verso.module. If set, it controls whether module docstrings use Verso syntax. If not set, it defaults to the value of thedoc.versooption. -
#12338 implements preparatory work for #12179. It implements a new feature in
isDefEqto ensure it does not increase the transparency level to.defaultwhen checking definitionally equality of implicit arguments. This transparency level bump was introduced in Lean 3, but it is not a performance issue and is affecting Mathlib. adds the new feature, but it is disabled by default. -
#12339 fixes a diamond problem in delta deriving where instance-implicit class parameters in the derived instance type were using instances synthesized for the underlying type, not the alias type.
-
#12340 implements better support for unfolding class fields marked as
reducible. For example, we want to mark fields that are types such asMonadControlT.stM : Type u -> Type u
The motivation is similar to our heuristic that type definitions should be abbreviations. Now, suppose we want to unfold
stM m (ExceptT Ξ΅ m) Ξ±using the.reducibletransparency setting, we want the result to bestM m m (MonadControl.stM m (ExceptT Ξ΅ m) Ξ±)instead of(instMonadControlTOfMonadControl m m (ExceptT Ξ΅ m)).1 Ξ±. The latter would defeat the intent of marking the field as reducible, since the instanceinstMonadControlTOfMonadControlis[instance_reducible]and the resulting term would be stuck when using.reducibletransparency mode. -
#12353 ressurects the dead trace class
Elab.resumeby redirecting the non-existantElab.resumingto it. -
#12355 adds
isBoolTrueExprandisBoolFalseExprfunctions toSymM -
#12391 makes
simpCondpublic. It is needed to avoid code duplication in #12361 -
#12395 adds
mvcgensupport for specifications in the local context. Example:import Std.Tactic.Do open Std.Do set_option mvcgen.warning false def foo (x : Id Nat β Id Nat) : Id Nat := do let rβ β x (pure 42) let rβ β x (pure 26) pure (rβ + rβ) theorem foo_spec (x : Id Nat β Id Nat) (x_spec : β (k : Id Nat) (_ : β¦βTrueββ¦ k β¦βr => βr % 2 = 0ββ¦), β¦βTrueββ¦ x k β¦βr => βr % 2 = 0ββ¦) : β¦βTrueββ¦ foo x β¦βr => βr % 2 = 0ββ¦ := by mvcgen [foo, x_spec] <;> grind def bar (k : Id Nat) : Id Nat := do let r β k if r > 30 then return 12 else return r example : β¦βTrueββ¦ foo bar β¦βr => βr % 2 = 0ββ¦ := by mvcgen [foo_spec, bar] -- unfold `bar` and automatically apply the spec for the higher-order argument `k` -
#12407 is similar to #12403.
-
#12416 makes
Sym.Simp.toBetaApppublic. This is necessary for the refactor of the maincbvsimproc in #12417. -
#12425 fixes a bug in
mvcgencaused by incompletematchsplitting. -
#12427 makes
mvcgensuggest to use-trivialwhen doing so avoids a recursion depth error. -
#12429 sets the
irreducibleattribute before generating the equations for recursive definitions. This prevents these equations to be marked asdefeq, which could lead tosimpgeneration proofs that do not type check at default transparency. -
#12451 provides the necessary hooks for the new do elaborator to call into the let and match elaborator.
-
#12459 adds a new, extensible
doelaborator. Users can opt into the new elaborator by unsetting the optionbackward.do.legacy. -
#12460 fixes an
AppBuilderexception in thecbvtactic when simplifying projections whose projection function is dependent (closes #12457). -
#12507 fixes #12495 where equational theorem generation fails for structurally recursive definitions using a Box-like wrapper around nested inductives.
-
#12514 improves universe level inference for the
inductiveandstructurecommands to be more reliable and to produce better error messages. Recall that the main constraint for inductive types is that ifuis the universe level for the type andu > 0, then each constructor field's universe levelvsatisfiesv β€ u, where a constructor field is an argument that is not one of the type's parameters (recall: the type's parameters are a prefix of the parameters shared by the type former and all the constructors). Given this constraint, theinductiveelaborator attempts to find reasonable assignments to metavariables that may be present:-
For the universe level
u, choosing an assignment that makes this level least is reasonable, provided it is unique. -
For constructor fields, choosing the unique assignment is usually reasonable.
-
For the type's parameters, promoting level metavariables to new universe level parameters is reasonable.
-
-
#12524 adds
Std.Iter.toHashSetand variants. -
#12525 adds declaration names to leanchecker error messages to make debugging easier when the kernel rejects a declaration.
-
#12530 improves the error message when
mvcgencannot resolve the name of a spec theorem. -
#12538 enables
backward.whnf.reducibleClassFieldfor v4.29. -
#12558 fixes a
(kernel) declaration has metavariableserror that occurred when abytactic was used in a dependent inductive type index that refers to a previous index:axiom P : Prop axiom Q : P β Prop -- Previously gave: (kernel) declaration has metavariables 'Foo' inductive Foo : (h : P) β (Q (by exact h)) β Prop
-
#12564 fixes
getStuckMVar?to detect stuck metavariables through auxiliary parent projections created for diamond inheritance. These coercions (e.g.,AddMonoid'.toAddZero') are not registered as regular projections because they construct the parent value from individual fields rather than extracting a single field. Previously,getStuckMVar?would give up when encountering them, preventing TC synthesis from being triggered. -
#12567 renames
instance_reducibletoimplicit_reducibleand adds a newbackward.isDefEq.implicitBumpoption to prepare for treating all implicit arguments uniformly during definitional equality checking. -
#12572 is part 2 of the
implicit_reduciblerefactoring (part 1: #12567). -
#12574 renames
SpecTheorems.addtoSpecTheorems.insert -
#12576 adds
Sym.mkPatternFromDeclWithKeyto the Sym API to generalize and implementSym.mkEqPatternFromDecl. This is useful to implement custom rewrite-like tactics that want to usePatterns for discrimination tree lookup. -
#12621 fixes a bug where
reduceRecMatcher?andreduceProj?bypassed the@[cbv_opaque]attribute. These kernel-level reduction functions usewhnfinternally, which does not know about@[cbv_opaque]. This meant@[cbv_opaque]values were unfolded when they appeared as match discriminants, recursor major premises, or projection targets. The fix introduceswithCbvOpaqueGuard, which wraps these calls withwithCanUnfoldPredto preventwhnffrom unfolding@[cbv_opaque]definitions. -
#12633 makes
isDefEqProjbump transparency to.instances(viawithInstanceConfig) when comparing the struct arguments of class projections. This makes the behavior consistent withisDefEqArgs, which already applies the same bump for instance-implicit parameters when comparing function applications. -
#12639 fixes the interaction between
backward.whnf.reducibleClassFieldandisDefEqDelta's argument-comparison heuristic. -
#12650 fixes a performance regression introduced by enabling
backward.whnf.reducibleClassField(https://github.com/leanprover/lean4/pull/12538). TheisNonTrivialRegularfunction inExprDefEqwas classifying class projections as nontrivial at all transparency levels, but the extra.instancesreduction inunfoldDefaultthat motivates this classification only applies at.reducibletransparency. At higher transparency levels, the nontrivial classification caused unnecessary heuristic comparison attempts inisDefEqDeltathat cascaded through BitVec reductions, causing elaboration ofLean.Data.Json.Parserto double from ~3.6G to ~7.2G instructions. -
#12698 adds a
result? : Option TraceResultfield toTraceDataand populates it inwithTraceNodeandwithTraceNodeBefore, so that metaprograms walking trace trees can determine success/failure structurally instead of string-matching on emoji. -
#12699 gives the
generatefunction's "apply @Foo to Goal" trace nodes their own trace sub-classMeta.synthInstance.applyinstead of sharing the parentMeta.synthInstanceclass. -
#12701 fixes a gap in how
@[implicit_reducible]is assigned to parent projections during structure elaboration. -
#12719 marks
levelZero,levelOne, andLevel.ofNatas@[implicit_reducible]so thatLevel.ofNat 0 =?= Level.zerosucceeds when the definitional equality checker respects transparency annotations. -
#12756 adds
deriving noncomputable instancesyntax so that delta-derived instances can be marked noncomputable. -
#12789 skips the noncomputable pre-check in
deriving instancewhen the instance type isProp, since proofs are erased by the compiler and computability is irrelevant. -
#12778 fixes an inconsistency in
getStuckMVar?where the instance argument to class projection functions and auxiliary parent projections was not whnf-normalized before checking for stuck metavariables. Every other case ingetStuckMVar?(recursors, quotient recursors,.projnodes) normalizes the major argument viawhnfbefore recursing β class projection functions and aux parent projections were the exception. -
#12897 adjusts the results of
inferInstanceAsand thedefderivinghandler to conform to recently strengthened restrictions on reducibility. When deriving or inferring an instance for a semireducible type definition, the definition's RHS is no longer leaked when the instance is reduced at lower than semireducible transparency. The synthesized instance's components (fields, nested instances) are unfolded and rewrapped as necessary. -
#13043 fixes a bug where
inferInstanceAsand the defaultderivinghandler, when used inside ameta section, would create auxiliary definitions (vianormalizeInstance) that were not marked asmeta. This caused the compiler to reject the parentmetadefinition with:Invalid `meta` definition `instEmptyCollectionNamePrefixRel`, `instEmptyCollectionNamePrefixRel._aux_1` not marked `meta`
-
#13059 switches the meta marking of auxiliary definitions created by
normalizeInstancefrom usingisMetaSectionto thedeclName?pattern, fixing a bug wherederivingin meta sections would fail because aux defs were incorrectly markedmetawhile the instance itself was not.
Library
-
#11811 proves that membership is preserved by eraseDups: an element exists in the deduplicated list iff it was in the original.
-
#11832 uses an
Arrayinstead of aListto store the clauses inStd.CNF. This reduces the memory footprint and pressure on the allocator, leading to noticeable performance changes with gigantic CNFs. -
#11936 provides
Arrayoperations analogous toList.min(?)andList.max(?). -
#11938 introduces projected minima and maxima, also known as "argmin/argmax", for lists under the names
List.minOnandList.maxOn. It also introducesList.minIdxOnandList.maxIdxOn, which return the index of the minimal or maximal element. Moreover, there are variants with?suffix that return anOption. The change further introduces new instances for opposite orders, such asLE.opposite,IsLinearOrder.oppositeetc. The change also adds the missingStd.lt_irrefllemma. -
#11943 introduces the theorem
BitVec.sshiftRight_eq_setWidth_extractLsb_signExtendtheorem, provingx.sshiftRight nis equivalent to first sign-extendingx, extracting the appropriate least significant bits, and then setting the width back tow. -
#11994 provides more lemmas about sums of lists/arrays/vectors, especially sums of
NatorIntlists/arrays/vectors. -
#12017 makes several small improvements to the list/array/vector API:
-
It fixes typos in
Init.Core. -
It adds
List.isSome_min_iffandList.isSome_max_iff. -
It adds
grindandsimpannotations to various previously unannotated lemmas. -
It adds lemmas for characterizing
β x β xs, P xusing indices asβ (i : Nat), β hi, P (xs[i]), and similar universally quantified lemmas:exists_mem_iff_exists_getElemandforall_mem_iff_forall_getElem. -
It adds
Vector.toList_zip. -
It adds
map_ofFnandofFn_getElemfor lists/arrays/vectors.
-
-
#12019 provides the
Nat/Intlemmasx β€ y * z β (x + z - 1) / z β€ y,x β€ y * z β (x + y - 1) / y β€ zandx / z + y / z β€ (x + y) / z. -
#12108 adds
prefix_map_iff_of_injectiveandsuffix_map_iff_of_injectivelemmas to Init.Data.List.Nat.Sublist. -
#12161 adds
Option.of_wp_eqandExcept.of_wp_eq, similar to the existingExcept.of_wp.Except.of_wpis deprecated because applying it requires prior generalization, at which point it is more convenient to useExcept.of_wp_eq. -
#12162 adds the function
Std.Iter.first?and proves the specification lemmaStd.Iter.first?_eq_match_stepif the iterator is productive. -
#12170 adjusts the grind annotations for List.take/drop, and adds two theorems.
-
#12181 adds two missing order instances for
Int. -
#12193 adds
DecidableEqinstances forSigmaandPSigma. -
#12204 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. -
#12212 adds the function
Std.Iter.isEmptyand proves the specification lemmasStd.Iter.isEmpty_eq_match_stepandStd.Iter.isEmpty_toListif the iterator is productive. -
#12220 fixes a bug on Windows with
IO.Process.spawnwhere setting an environment variable to the empty string would not set the environment variable on the subprocess. -
#12234 introduces an
Iter.step_eqlemma that fully unfolds anIter.stepcall, bypassing layers of unfolding. -
#12249 adds some lemmas about the interaction of
sum,minandmaxabout arrays that already exist for lists. -
#12250 introduces the defining equality
Triple.iffand uses that in proofs instead of relying on definitional equality. It also introducesTriple.iff_conseqthat is useful for backward reasoning and introduces verification conditions. Similarly,Triple.entails_wp_*theorems are introduced for backward reasoning where the target is an stateful entailment rather than a triple. -
#12258 adds theorems that directly state that div and mod form an injective pair: if
a / n = b / nanda % n = b % nthena = b. These complement existing div/mod lemmas and are useful for extension arguments. -
#12277 adds
IO.FS.Metadata.numLinks, which contains the number of hard links to a file. -
#12281 changes the definition of
Squashto useQuotientby upstreamingtrue_equivalence(nowequivalence_true) andtrueSetoid(nowSetoid.trivial). The new definition is def-eq to the old one, but ensures thatSquashcan be used whenever aQuotientargument is expected without having to explicitly provide the setoid. -
#12282 fixes a platform inconsistency in
IO.FS.removeFilewhere it could not delete read-only files on Windows. -
#12290 moves the
PredTrans.applystructure field into a separatedef. Doing so improves kernel reduction speed because the kernel is less likely to unfold definitions compared to structure field projections. This causes minor shifts insimpnormal forms. -
#12301 introduces the functions
(String|Slice).posGEand(String|Slice).posGTwill full verification and deprecatesSlice.findNextPosin favor ofSlice.posGT. -
#12305 adds various uninteresting lemmas about basic types, extracted from the KMP verification.
-
#12311 exposes the chain and
is_supdefinitions such that other modules can declare custom CCPO instances. -
#12312 reverses the relationship between the
ForwardPatternandToForwardSearcherclasses. -
#12318 avoids undefined behavior in
String.Slice.hashon unaligned substrings. This could produce a SIGILL on some Arm platforms. -
#12322 adds
String.Slice.Subslice, which is an unbundled version ofString.Slice. -
#12333 adds the basic typeclasses that will be used in the verification of our string searching infrastructure.
-
#12341 adds a few unification hints that we will need after
backward.isDefEq.respectTransparencyistrueby default. -
#12346 shows
s == t β s.copy = t.copyfors t : String.Sliceand establishes the right-hand side as the simp normal form. -
#12349 builds on #12333 and proves that
CharandChar -> Boolpatterns are lawful. -
#12352 improves the slice API with lemmas for
drop/takeoperations onSubarrayand more lemmas aboutStd.Slice.fold,Std.Slice.foldMandStd.Slice.forIn. It also changes thesimpandgrindannotations forSlice-related lemmas. Lemmas converting between slices of different shapes are no longersimp/grind-annotated because they often complicated lemmas and hindered automation. -
#12358 improves the
simpandgrindrule framework forPredTrans.applyand also renames the respective lemmas according to convention. -
#12359 deprecates
extract_eq_drop_takein favor of the more correct nameextract_eq_take_drop, so that we'll be able to use the old name for a lemmaxs.extract start stop = (xs.take stop).drop start. Until the deprecation deadline has passed, this new lemma will be calledextract_eq_drop_take'. -
#12360 provides a
LawfulForwardPatternModelinstance for string patterns, i.e., it proves correctness of thedropPrefix?andstartsWithfunctions for string patterns. -
#12363 introduces iterators for vectors via
Vector.iterandVector.iterM, together with the usual lemmas. -
#12371 adds lemmas for simplifying situations involving
Boolandite/dite. -
#12412 introduces
Rat.absand adds missing lemmas aboutIntandRat. -
#12419 adds
LawfulOrderOrdinstances forNat,Int, and all fixed-width integer types (Int8,Int16,Int32,Int64,ISize,UInt8,UInt16,UInt32,UInt64,USize). These instances establish that theOrdinstances for these types are compatible with theirLEinstances. Additionally, this PR adds a few missing lemmas andgrindpatterns. -
#12424 gives a proof of
LawfulToForwardSearcherModelforSlicepatterns, which amounts to proving that our implementation of KMP is correct. -
#12426 adds the lemma
Acc.inv_of_transGen, a generalization ofAcc.inv. WhileAcc.invshows thatAcc r ximpliesAcc r ygiven thatr y x, the new lemma shows that this also holds ifyis only transitively related tox. -
#12432 adds the lemmas
isSome_find?andisSome_findSome?to the API of lists, arrays and vectors. -
#12437 verifies the
String.Slice.splitToSubslicefunction by relating it to a model implementationModel.splitbased on aForwardPatternModel. -
#12438 provides (1) lemmas showing that lists obtained from ranges have no duplicates and (2) lemmas about
forInandfoldlon slices. -
#12441 removes
Subarray.foldl(M),Subarray.toArrayandSubarray.sizein favor of theStd.Slice-namespaced operations. Dot notation will continue to work. If, say,Subarray.sizeis explicitly referred to, an error suggesting to useStd.Slice.sizewill show up. -
#12442 derives
DecidableEqinstances for the types of ranges such asa...b(in this case,Std.Rco). -
#12445 provides lemmas characterizing
Nat.toDigits,Nat.reprandToString Nat. -
#12449 marks
String.toString_eq_singletonas asimplemma. -
#12450 moves the
String.Slice/Stringiterators out into their own file, in preparation for verification. -
#12452 upstreams
List.scanl,List.scanrand their lemmas from batteries into the standard library. -
#12456 verifies all of the
Stringiterators except for the bytes iterator by relating them toString.toList. -
#12504 makes the
Rat.abs_*lemmas (abs_zero,abs_nonneg,abs_of_nonneg,abs_of_nonpos,abs_neg,abs_sub_comm,abs_eq_zero_iff,abs_pos_iff) protected, so they don't shadow the generalabs_*lemmas when theRatnamespace is opened in downstream projects. -
#12521 shows
HashSet.ofList l ~m l.foldl (init := β ) fun acc a => acc.insert a(which is "just" the definition). -
#12531 bundles some lemmas about hash maps into equivalences for easier rewriting.
-
#12582 uses a
ptrEqfast path forName.quickCmp. It is particularly effective at speeding upquickCmpcalls inTreeMap's indexed byFVarIdas usually there is only one pointer perFVarIdso equality is always instantly detected without traversing the linked list ofNamecomponents. -
#12583 inlines the accessor for the computed hash field of
Name. This ensures that accessing the value is basically always just a single load instead of doing a full function call. -
#12596 adds an
Std.Dospec lemma forForInover strings. -
#12641 derives the linear order on string positions (
String.Pos.Raw,String.Pos,String.Slice.Pos) viaStd.LinearOrderPackage, which ensures that all data-carrying and propositional instances are present. -
#12642 adds dsimprocs for reducing
String.toListandString.push. -
#12651 adds some missing lemmas about
min,minOn,List.min,List.minOn. -
#12757 marks
Id.runas[implicit_reducible]to ensure thatId.instMonadLiftTOfPureandinstMonadLiftT Idare definitionally equal when using.implicitReducibletransparency setting. -
#12821 removes the
@[grind β]attribute fromList.getElem_of_getElem?andVector.getElem_of_getElem?. These were identified as problematic in Mathlib by https://github.com/leanprover/lean4/issues/12805.
Tactics
-
#11744 fixes a bug where
liawas incorrectly solving goals involving ordered types likeRatthat it shouldn't handle. Theliatactic is intended for linear integer arithmetic only. -
#12152 adds
simpArrowTelescope, a simproc that simplifies telescopes of non-dependent arrows (pβ β pβ β ... β q) while avoiding quadratic proof growth. -
#12153 improves the
simpArrowTelescopesimproc that simplifies non-dependent arrow telescopes:pβ β pβ β ... β q. -
#12154 adds
simpTelescope, a simproc that simplifies telescope binders (have-expression values and arrow hypotheses) but not the final body. This is useful for simplifying targets before introducing hypotheses. -
#12168 adds support for eta-reduction in
SymM. -
#12172 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:structure OrdSet (Ξ± : Type) [Hashable Ξ±] [BEq Ξ±] where ... def OrdSet.insert {_ : Hashable Ξ±} {_ : BEq Ξ±} (s : OrdSet Ξ±) (a : Ξ±) : OrdSet Ξ± := ...Here,
HashableandBEqare classes, but the{..}binder is intentional, the instances come fromOrdSet'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 inFunInfo. This affects several subsystems: discrimination trees, congruence lemma generation, and thegrindcanonicalizer. -
#12176 fixes a bug where delayed E-match theorem instances could cause uniqueId collisions in the instance tracking map.
-
#12195 ensures
dsimpdoes not "simplify" instances by default. The old behavior can be retrieved by usingset_option backward.dsimp.instances true
Applying
dsimpto instances creates non-standard instances, and this creates all sorts of problems in Mathlib. This modification is similar toset_option backward.dsimp.proofs true
-
#12205 adds
mkBackwardRuleFromExprto create backward rules from expressions, complementing the existingmkBackwardRuleFromDeclwhich only works with declaration names. -
#12224 fixes a bug where
grind?suggestions would not include parameters using local variable dot notation (e.g.,cs.getD_rightInvSeqwherecsis a local variable). These parameters were incorrectly filtered out because the code assumed all ident params resolve to global declarations. In fact, local variable dot notation produces anchors that need the original term to be loaded during replay, so they must be preserved in the suggestion. -
#12226 fixes a bug where
grind [foo]fails when the theoremfoohas a different universe variable name than the goal, even though universe polymorphism should allow the universes to unify. -
#12244 ensures
simpdoes not "simplify" instances by default. The old behavior can be retrieved by usingsimp +instances. is similar to #12195, but fordsimp. The backward compatibility flag fordsimpalso deactivates this new feature. -
#12259 ensures we cache the result of
unfold_definitiondefinition in the kernel type checker. We used to cache this information in a thread local storage, but it was deleted during the Lean 3 to Lean 4 transition. -
#12260 fixes a bug in the function
instantiateRangeS'in theSymframework. -
#12279 adds an experimental
cbvtactic that can be invoked fromconvmode. The tactic is not suitable for production use and an appropriate warning is displayed. -
#12280 adds a benchmark based on Xavier Leroy's compiler verification course to test call-by-value tactic.
-
#12287 fixes an issue where
attribute [local simp]was incorrectly rejected on a theorem from a private import -
#12296 adds
cbv_evalattribute that allows to evaluate functions incbvtactic using pre-registered theorems. -
#12319 leverages the fact that expressions are type correct in
grindand the conclusion of extensionality theorems is of the form?a = ?b. -
#12345 adds two benchmarks (sieve of Eratosthenes, removing duplicates from the list) and one test (a function with sublinear complexity defined via well-founded recursion evaluated on large naturals with up to
60digits). -
#12361 develops custom simprocs for dealing with
ite/diteexpressions incbvtactics, based on equivalent simprocs fromSym.simp, with the difference that if the condition is not reduced toTrue/False, we make use of the decidable instance and calculate to what the condition reduces to. -
#12370 fixes a proof construction bug in
Sym.simp. -
#12399 adds a custom simproc to handle
Decidable.rec, where we force the rewrite in the argument of theDecidabletype, that normally is not rewritten due to being a subsingleton. -
#12406 implements two changes to LRAT checking in
bv_decide:-
The LRAT trimmer previously used to drop delete instructions as we did not act upon them in a meaningful way (as explained in 2). Now it figures out the earliest point after which a clause may be deleted in the trimmed LRAT proof and inserts a deletion there.
-
The LRAT checker takes in an
Array IntActionand explodes it into anArray DefaultClauseActionbefore passing it into the checking loop.DefaultClauseActionhas a much larger memory footprint compared toIntAction. Thus materializing the entire proof asDefaultClauseActionupfront consumes a lot of memory. In the adapted LRAT checker we take in anArray IntActionand only ever convert the step we are currently working on to aDefaultClauseAction. In combination with the fact that we now insert deletion instructions this can drastically reduce memory consumption.
-
-
#12408 adds a user facing
cbvtactic that can be used outside of theconvmode. -
#12411 adds a finishing
decide_cbvtactic, which appliesof_decide_eq_trueand then tries to discharge the remaining goal usingcbv. -
#12415 improves the support for eta expanded terms in
grindpatterns. -
#12417 refactors the main loop of the
cbvtactic. Rather than using multiple simprocs, a central pre simproc is introduced. Moreover, let expressions are no longer immediately zeta-reduced due to performance on one of the benchmarks (leroy.lean). -
#12423 adds the attribute
@[univ_out_params]for specifying which universe levels should be treated as output parameters. By default, any universe level that does not occur in any input parameter is considered an output parameter. -
#12467 adds a benchmark for
cbvtactic for evaluatingDecidable.decidefor aDecidableinstance for a problem of checking if a number is not a prime power. -
#12473 fixes an assertion violation in
grindreported at #12246 This assertion fails when in examples containing heterogenous equalities with elements of different types (e.g.,Fin nandFin m) attached to the same theory solver. -
#12474 fixes a panic in
grindwheresreifyCore?could encounter power subterms not yet internalized in the E-graph during nested propagation. The ring reifier (reifyCore?) already had a defensivealreadyInternalizedcheck before creating variables, but the semiring reifier (sreifyCore?) was missing this guard. WhenpropagatePowerdecomposeda ^ (bβ + bβ)intoa^bβ * a^bβand the resulting terms triggered further propagation, the semiring reifier could be called on subterms not yet in the E-graph, causingmarkTermto fail. -
#12475 fixes
grindfailing when hypotheses contain metavariables (e.g., afterrefine). The root cause was thatabstractMVarsinwithProtectedMCtxonly abstracted metavariables in the target, not in hypotheses, creating a disconnect in grind's e-graph. -
#12476 fixes #12245 where
grindworks onFin nbut fails onFin (n + 1). -
#12477 fixes an internal
grinderror wheremkEqProofis invoked with terms of different types. When equivalence classes contain heterogeneous equalities (e.g.,0 : Fin 3and0 : Fin 2merged viaHEq),closeGoalWithValuesEqwould callmkEqProofon terms with incompatible types, triggering an internal error. -
#12480 skips the relabeling step during AIG to CNF conversion, reducing memory pressure.
-
#12483 adds support for higher-order Miller patterns in
grind's e-matching engine. -
#12486 caches
isDefEqIresults inSym. During symbolic computation (e.g., VC generators), we find the same instances over and over again. -
#12500 improves the error messages produced by the
decide_cbvtactic by only reducing the left-hand side of the equality introduced byof_decide_eq_true, rather than attempting to reduce both sides viacbvGoal. -
#12506 adds the ability to register theorems with the
cbv_evalattribute in the reverse direction using theβmodifier, mirroring the existingsimpattribute behavior. When@[cbv_eval β]is used, the equationlhs = rhsis inverted torhs = lhs, allowingcbvto rewrite occurrences ofrhstolhs. -
#12562 fixes #12554 where the
cbvtactic throws "unexpected kernel projection term during structural definitional equality" when a rewrite theorem's pattern contains a lambda and the expression being matched has a.proj(kernel projection) at the corresponding position. -
#12568 removes
tryMatchEquationsandtryMatcherfromLean.Meta.Tactic.Cbv.Main, as both are already defined and used inLean.Meta.Tactic.Cbv.ControlFlow. The copies inMain.leanwere unreachable dead code. -
#12585 removes unnecessary
trySynthInstanceiniteandditesimprocs used bycbvthat previously contributed to too much of unnecessary unrolling by the tactic. -
#12588 adds a benchmark for
cbvtactic that involves evaluatingList.mergeSorton a reversed list on natural numbers. -
#12601 adds a warning when using
cbvordecide_cbvin tactic mode, matching the existing warning in conv mode (src/Lean/Elab/Tactic/Conv/Cbv.lean). The warning informs users that these tactics are experimental and still under development. It can be disabled withset_option cbv.warning false. -
#12612 fixes a crash in the
cbvtactic'shandleProjsimproc when processing a dependent projection (e.g.Sigma.snd) whose struct is rewritten via@[cbv_eval]to a non-definitionally-equal term that cannot be further reduced. -
#12615 fixes a flipped condition in
handleConstthat preventedcbvfrom unfolding nullary (non-function) constant definitions likedef myVal : Nat := 42. The checkunless eType matches .forallEwas intended to skip bare function constants (whose unfold theorems expect arguments) but instead skipped value constants. The fix changes the guard toif eType matches .forallE, matching the logic used in the standardsimpground evaluator. -
#12622 fixes a bug where
simpmade no progress on class projection reductions whenbackward.whnf.reducibleClassFieldistrue. -
#12627 reverts #12615, which accidentally broke Leroy's compiler verification course benchmark.
-
#12646 enables the
cbvtactic to unfold nullary (non-function) constant definitions such asdef myNat : Nat := 42, allowing ground term evaluation (e.g.evalEq,evalLT) to recognize their values as literals. -
#12782 adds high priority to instances for
OfSemiring.Qin the grind ring envelope. When Mathlib is imported, instance synthesis for types likeOfSemiring.Q Natbecomes very expensive because the solver explores many irrelevant paths before finding the correct instances. By marking these instances as high priority and adding shortcut instances for basic operations (Add,Sub,Mul,Neg,OfNat,NatCast,IntCast,HPow), instance synthesis resolves quickly.
Compiler
-
#12044 implements lazy initialization of closed terms. Previous work has already made sure that ~70% of the closed terms occurring in core can be statically initialized from the binary. With this the remaining ones are initialized lazily instead of at startup.
-
#12052 avoids a potential deadlock on shutdown of a Lean program when the number of pooled threads has temporarily been pushed above the limit.
-
#12060 strips unneeded symbol names from libleanshared.so on Linux. It appears that on other platforms the symbols names we are interested in here are already removed by the linker.
-
#12082 makes the compiler produce C code that statically initializes close terms when possible. This change reduces startup time as the terms are directly stored in the binary instead of getting computed at startup.
-
#12117 upgrades Lean's internal toolchain to use C++20 as a preparatory step for #12044.
-
#12214 introduces a phase separation to the LCNF IR. This is a preparation for the merge of the old
Lean.Compiler.IRand the newLean.Compiler.LCNFframework. -
#12239 reverts a lot of the changes done in #8308. We practically encountered situations such as:
fun y (z) := let x := inst mkInst x z f y
Where the instance puller turns it into:
let x := inst fun y (z) := mkInst x z f y
The current heuristic now discovers
xbeing in scope at the call site offand being used under a binder inyand thus blocks pulling inxto the specialization, abstracting over an instance. -
#12272 shifts the conversion from LCNF mono to lambda pure into the LCNF impure phase. This is preparatory work for the upcoming refactor of IR into LCNF impure.
-
#12284 changes the handling of over-applied cases expressions in
ToLCNFto avoid generating function declarations that are called immediately. For example,ToLCNFpreviously produced this:set_option trace.Compiler.init true /-- trace: [Compiler.init] size: 4 def test x y : Bool := fun _y.1 _y.2 : Bool := cases x : Bool | PUnit.unit => fun _f.3 a : Bool := return a; let _x.4 := _f.3 _y.2; return _x.4; let _x.5 := _y.1 y; return _x.5 -/ #guard_msgs in def test (x : Unit) (y : Bool) : Bool := x.casesOn (fun a => a) ywhich is now simplified to
set_option trace.Compiler.init true /-- trace: [Compiler.init] size: 3 def test x y : Bool := cases x : Bool | PUnit.unit => let a := y; return a -/ #guard_msgs in def test (x : Unit) (y : Bool) : Bool := x.casesOn (fun a => a) yThis is especially relevant for #8309 because there
diteis defined as an over-appliedBool.casesOn. -
#12294 ports the
push_projpass from IR to LCNF. Notably it cannot delete it from IR yet as the pass is still used later on. -
#12315 migrates the IR ResetReuse pass to LCNF.
-
#12344 changes the semantics of
inlineannotations in the compiler. The behavior of the original@[inline]attribute remains the same but the functioninlinenow comes with a restriction that it can only use declarations that are local to the current module. This comes as a preparation to pulling the compiler out into a separate process. -
#12356 moves the IR
elim_dead_varspass to LCNF. It cannot delete the pass yet as it is still used in later IR passes. -
#12384 ports the IR SimpCase pass to LCNF.
-
#12387 fixes an issue in LCNF simp where it would attempt to act on type incorrect
casesstatements and look for a branch, otherwise panic. This issue did not yet manifest in production as various other invariants upheld by LCNF simp help mask it but will start to become an issue with the upcoming changes. -
#12413 ports the IR borrow pass to LCNF.
-
#12434 removes the uses of
shared_timed_mutexthat were introduced because we were stuck on C++14 with theshared_mutexavailable from C++17 and above. -
#12446 adds a simplification rule for
Task.get (Task.pure x) = xinto the LCNF simplifier. This ensures that we avoid touching the runtime for aTaskthat instantly gets destructed anyways. -
#12458 ports the IR pass for box/unbox insertion to LCNF.
-
#12465 changes the boxed type of
uint64fromtobjecttoobjectto allow for more precise reference counting. -
#12466 handles zero-sized reads on handles correctly by returning an empty array before the syscall is even attempted.
-
#12472 inlines
mix_hashfrom C++ which provides general speedups for hash functions. -
#12548 ports the RC insertion from IR to LCNF.
-
#12580 makes
computed_fieldrespect the inline attributes on the function for computing the field. This means we can inline the accessor for the field, allowing quicker access. -
#12604 makes the derived value analysis in RC insertion recognize
Array.ugetas another kind of "projection-like" operation. This allows it to reduce reference count pressure on elements accessed through uget. -
#12625 ensures that failure in initial compilation marks the relevant definitions as
noncomputable, inside and outsidenoncomputable section, so that follow-up errors/noncomputable markings are detected in initial compilation as well instead of somewhere down the pipeline. -
#12644 ports the toposorting pass from IR to LCNF.
-
#12759 replaces the
isImplicitReduciblecheck withMeta.isInstancein theshouldInlinefunction withininlineCandidate?.
Pretty Printing
-
#12688 adds the
pp.fvars.anonymousoption (defaulttrue) that controls the display of loose free variables (fvars not in the local context). Whenfalse, they display as_fvar._instead of their internal name. This is useful for stabilizing output in#guard_msgs. #12745 fixes the behavior when the option is set tofalse.
Documentation
-
#12157 updates #12137 with a link to the Lean reference manual.
-
#12174 fixes a typo in
ExtractLetsConfig.mergedoc comment. -
#12253 adds a "Stabilizing output" section to the
#guard_msgsdocstring, explaining how to usepp.mvars.anonymousandpp.mvarsoptions to stabilize output containing autogenerated metavariable names like?m.47. -
#12271 adds and updates docstrings for syntax (and one for ranges).
-
#12439 improves docstrings for
cbvanddecide_cbvtactics -
#12487 expands the docstring for
@[univ_out_params]to explain:-
How universe output parameters affect the typeclass resolution cache (they are erased from cache keys, so queries differing only in output universes share entries)
-
When a universe parameter should be considered an output (determined by inputs) vs. not (part of the question being asked)
-
-
#12616 adds documentation to the Cbv evaluator files under
Meta/Tactic/Cbv/. Module docstrings describe the evaluation strategy, limitations, attributes, and unfolding order. Function docstrings cover the public API and key internal simprocs. -
#13115 updates the
inferInstanceAsdocstring to reflect current behavior: it requires an expected type from context and should not be used as a simpleinferInstancesynonym. The old example (#check inferInstanceAs (Inhabited Nat)) no longer works, so it's replaced with one demonstrating the intended transport use case.
Server
-
#12197 fixes a bug in
System.Uri.fileUriToPath?where it wouldn't use the default Windows path separator in the path it produces. -
#12332 fixes an issue on new NeoVim versions that would cause the language server to display an error when using certain code actions.
-
#12553 fixes an issue where commands that do not support incrementality did not have their elaboration interrupted when a relevant edit is made by the user. As all built-in variants of def/theorem share a common incremental elaborator, this likely had negligible impact on standard Lean files but could affect other use cases heavily relying on custom commands such as Verso.
Lake
-
#12113 changes the alters the file format of outputs stored in the local Lake cache to include an identifier indicating the service (if any) the output came from. This will be used to enable lazily downloading artifacts on-demand during builds.
-
#12178 scopes the
simpattribute onFamilyOut.fam_eqto theLakenamespace. The lemma has a very permissive discrimination tree key (_), so whenLake.Util.Familyis transitively imported into downstream projects, it causessimpto attempt this lemma on every goal, leading to timeouts. -
#12203 changes the way artifacts are transferred from the local Lake cache to a local build path. Now, Lake will first attempt to hard link the local build path to artifact in the cache. If this fails (e.g., because the cache is on a different file system or drive), it will fallback to pre-existing approach of copying the artifact. Lake also now marks cache artifacts as read-only to avoid corrupting the cache by writing to a hard linked artifact.
-
#12261 fixes a bug in Lake where the facet names printed in unknown facet errors would contain the internal facet kind.
-
#12300 makes disabling the artifact cache (e.g., via
LAKE_ARTIFACT_CACHE=falseorenableArtifactCache = false) now stop Lake from fetching from the cache (whereas it previously only stopped writing to it). -
#12377 adds identifying information about a module available to
lean(e.g., its name and package identifier) to the module's dependency trace. This ensures modules with different identification have different input hashes even if their source files and imports are identical. -
#12444 adds the Lake CLI command
lake cache clean, which deletes the Lake cache directory. -
#12461 adds support for manually re-releasing nightlies when a build issue or critical fix requires it. When a
workflow_dispatchtriggers the nightly release job and anightly-YYYY-MM-DDtag already exists, the CI now createsnightly-YYYY-MM-DD-rev1(then-rev2, etc.) instead of silently skipping. -
#12490 adds a system-wide Lake configuration file and uses it to configure the remote cache services used by
lake cache. -
#12532 fixes a bug with
cache cleanwhere it would fail if the cache directory does not exist. -
#12537 fixes a bug where Lake recached artifacts already present within the cache. As a result, Lake would attempt to overwrite the read-only artifacts, causing a permission denied error.
-
#12835 changes Lake to only emit
.nobuildtraces (introduced in #12076) if the normal trace file already exists. This fixes an issue where alake build --no-buildwould create the build directory and thereby prevent a cloud release fetch in a future build. -
#13141 changes Lake to run
git clean -xfwhen updating dependency repositories, ensuring stale untracked files (such as.hashfiles) in the source tree are removed. Stale.hashfiles could cause incorrect trace computation and break builds.
Other
-
#12351 extends the
@[csimp]attribute to be correctly tracked bylake shake -
#12375 extends shake with tracking of attribute names passed to
simp/grind. -
#12463 fixes two issues discovered during the first test of the revised nightly release workflow (https://github.com/leanprover/lean4/pull/12461):
1. Date logic: The
workflow_dispatchpath useddate -u +%F(current UTC date) to find the base nightly to revise. If the most recent nightly was from yesterday (e.g.nightly-2026-02-12) but UTC has rolled over to Feb 13, the code would look fornightly-2026-02-13, not find it, and create a fresh nightly instead of a revision. Now finds the latestnightly-*tag viasort -rVand creates a revision of that. -
#12517 adds tooling for profiling Lean programs with human-readable function names in Firefox Profiler:
-
script/lean_profile.shβ One-command pipeline: record with samply, symbolicate, demangle, and open in Firefox Profiler -
script/profiler/lean_demangle.pyβ Faithful port ofName.demangleAuxfromNameMangling.lean, with a postprocessor that folds compiler suffixes into compact annotations ([Ξ», arityβ],spec at context[flags]) -
script/profiler/symbolicate_profile.pyβ Resolves raw addresses via samply's symbolication API -
script/profiler/serve_profile.pyβ Serves demangled profiles to Firefox Profiler without re-symbolication -
PROFILER_README.mdβ Documentation including a guide to reading demangled names
-
-
#12533 adds human-friendly demangling of Lean symbol names in runtime backtraces. When a Lean program panics, stack traces now show readable names instead of mangled C identifiers.