Lean 4.28.0-rc1 (2026-01-26)
For this release, 309 changes landed. In addition to the 94 feature additions and 65 fixes listed below there were 19 refactoring changes, 8 documentation improvements, 34 performance improvements, 12 improvements to the test suite and 77 other changes.
Language
-
#11553 makes
simpH, used in the match equation generator, produce a proof term. This is in preparation for a bigger refactoring in #11512. -
#11666 makes sure that when a matcher is compiled using a sparse cases, that equation generation also uses sparse cases to split. This fixes #11665.
-
#11669 makes sure that proofs about
ctorIdxpassed togrindpass thedebug.grindchecks, despite reducing asemireducibledefinition. -
#11670 fixes the
grindsupport forNat.ctorIdx. Nat constructors appear ingrindas offsets or literals, and not as a node marked.constr, so handle that case as well. -
#11673 fixes an issue where a
byin the public scope could create an auxiliary theorem for the proof whose type does not match the expected type in the public scope. -
#11696 improves
matchgeneralization such that it abstracts metavariables in types of local variables and in the result type of the match over the match discriminants. Previously, a metavariable in the result type would silently default to the behavior ofgeneralizing := false, and a metavariable in the type of a free variable would lead to an error (#8099). Example of amatchthat elaborates now but previously wouldn't:example (a : Nat) (ha : a = 37) := (match a with | 42 => by contradiction | n => n) = 37This is because the result type of the
matchis a metavariable that was not abstracted overaand hence generalization failed; the result is thatcontradictioncannot pick up the proofha : 42 = 37. The old behavior can be recovered by passing(generalizing := false)to thematch. -
#11698 makes
mvcgenearly return after simplifying discriminants, avoiding a rewrite on an ill-formedmatch. -
#11714 gives a focused error message when a user tries to name an example, and tweaks error messages for attempts to define multiple opaque names at once.
-
#11718 adds a test for issue #11655, which it seems was fixed by #11695
-
#11721 improves the performance of the functions for generating congruence lemmas, used by
simpand a few other components. -
#11726 upstreams dependency-management commands from Mathlib:
-
#import_path Fooprints the transitive import chain that bringsFoointo scope -
assert_not_exists Fooerrors if declarationFooexists (for dependency management) -
assert_not_imported Modulewarns ifModuleis transitively imported -
#check_assertionsverifies all pending assertions are eventually satisfied
-
-
#11731 makes the cache in expreqfn use mimalloc for a small performance win across the board.
-
#11748 fixes an edge case where some tactics did not allow access to private declarations inside private proofs under the module system
-
#11756 fixes an issue where
grindfails when trying to unfold a definition by pattern matching imported byimport all(or from a non-module). -
#11780 ensures that pretty-printing of unification hints inserts a space after |- resp. ⊢.
-
#11871 makes
mvcgen with tacfail iftacfails on one of the VCs, just asinduction ... with tacfails iftacfails on one of the goals. The old behavior can be recovered by writingmvcgen with try tacinstead. -
#11875 adds the directory
Meta/DiscrTreeand reorganizes the code into different files. Motivation: we are going to have new functions for retrieving simplification theorems for the new structural simplifier. -
#11882 adds a guard to
TagDeclarationExtension.tagto check if the declaration name is anonymous and return early if so. This prevents a panic that could occur when modifiers likemetaornoncomputableare used in combination with syntax errors. -
#11896 fixes a panic that occurred when a theorem had a docstring on an auxiliary definition within a
whereclause. -
#11908 adds two features to the message testing commands: a new
#guard_paniccommand that succeeds if the nested command produces a panic message (useful for testing commands expected to panic), and asubstring := trueoption for#guard_msgsthat checks if the docstring appears as a substring of the output rather than requiring an exact match. -
#11919 improves the error message when
initialize(oropaque) fails to find anInhabitedorNonemptyinstance. -
#11926 adds an
unsafemodifier to an existing helper function userunsafeEIO, and also leaves the function private. -
#11933 adds utility functions for managing the message log during tactic evaluation, and refactors existing code to use them.
-
#11940 fixes module system visibiltity issues when trying to declare a public inductive inside a mutual block.
-
#11941 reverts #11696.
-
#11991 fixes
declare_syntax_catdeclaring a local category leading to import errors when used inmodulewithoutpublic section. -
#12026 fixes an issue where attributes like
@[irreducible]would not be allowed under the module system unless combined with@[exposed], but the former may be helpful without the latter to ensure downstream non-modules are also affected. -
#12045 disables the
import allcheck across package boundaries. Now any module canimport allany other module. -
#12048 fixes a bug where
mvcgenloses VCs, resulting in unassigned metavariables. It is fixed by making all emitted VCs synthetic opaque. -
#12122 adds support for Verso docstrings in
whereclauses. -
#12148 reverts #12000, which introduced a regression where
simpincorrectly rejects valid rewrites for perm lemmas.
Library
-
#11257 adds the definition of
BitVec.cpop, which relies on the more generalBitVec.cpopNatRec, and build some theory around it. The namecpopaligns with the RISCV ISA nomenclature. -
#11438 renames the namespace
Std.RangetoStd.Legacy.Range. Instead of usingStd.Rangeand[a:b]notation, the new range typeStd.Rcoand its correspondinga...bnotation should be used. There are also other ranges with open/closed/infinite boundary shapes inStd.Data.Range.Polymorphicand the new range notation also works forInt,Int8,UInt8,Finetc. -
#11446 moves many constants of the iterator API from
Std.Iteratorsto theStdnamespace in order to make them more convenient to use. These constants include, but are not limited to,Iter,IterMandIteratorLoop. This is a breaking change. If something breaks, try addingopen Stdin order to make these constants available again. If some constants in theStd.Iteratorsnamespace cannot be found, they can be found directly inStdnow. -
#11499 adds the
Contexttype for cancellation with context propagation. It works by storing a tree of forks of the main context, providing a way to control cancellation. -
#11532 adds the new operation
MonadAttach.attachthat attaches a proof that a postcondition holds to the return value of a monadic operation. Most non-CPS monads in the standard library support this operation in a nontrivial way. The PR also changes thefilterMapM,mapMandflatMapMcombinators so that they attach postconditions to the user-provided monadic functions passed to them. This makes it possible to prove termination for some of these for which it wasn't possible before. Additionally, the PR adds many missing lemmas aboutfilterMap(M)andmap(M)that were needed in the course of this PR. -
#11693 makes it possible to verify loops over iterators. It provides MPL spec lemmas about
forloops over pure iterators. It also provides spec lemmas that rewrite loops overmapM,filterMapMorfilterMiterator combinators into loops over their base iterator. -
#11705 provides many lemmas about
Intranges, in analogy to those aboutNatranges. A few necessary basicIntlemmas are added. The PR also removessimpannotations onRcc.toList_eq_toList_rco,Nat.toList_rcc_eq_toList_rcoand consorts. -
#11706 removes the
IteratorCollecttype class and hereby simplifies the iterator API. Its limited advantages did not justify the complexity cost. -
#11710 extends the get-elem tactic for ranges so that it supports subarrays. Example:
example {a : Array Nat} (h : a.size = 28) : Id Unit := do let mut x := 0 for h : i in *...(3 : Nat) do x := a[1...4][i] -
#11716 adds more MPL spec lemmas for all combinations of
forloops,fold(M)and thefilter(M)/filterMap(M)/map(M)iterator combinators. These kinds of loops over these combinators (e.g.it.mapM) are first transformed into loops over their base iterators (it), and if the base iterator is of typeIter _orIterM Id _, then another spec lemma exists for proving Hoare triples about it using an invariant and the underlying list (it.toList). The PR also fixes a bug that MPL always assigns the default priority to spec lemmas ifStd.Tactic.Do.Syntaxis not imported and a bug that low-priority lemmas are preferred about high-priority ones. -
#11724 adds more
event_loop_locks to fix race conditions. -
#11728 introduces some additional lemmas around
BitVec.extractLsb'andBitVec.extractLsb. -
#11760 allows
grindto useList.eq_nil_of_length_eq_zero(andArray.eq_empty_of_size_eq_zero), but only when it has already proved the length is zero. -
#11761 adds some
grind_patternguardconditions to potentially expensive theorems. -
#11762 moves the grind pattern from
Sublist.eq_of_lengthto the slightly more generalSublist.eq_of_length_le, and adds a grind pattern guard so it only activates if we have a proof of the hypothesis. -
#11767 introduces two induction principles for bitvectors, based on the concat and cons operations. We show how this principle can be useful to reason about bitvectors by refactoring two population count lemmas (
cpopNatRec_zero_leandtoNat_cpop_append) and introducing a new lemma (toNat_cpop_not). To use the induction principle we also movecpopNatRec_cons_of_leandcpopNatRec_cons_of_ltearlier in the popcount section (they are the building blocks enabling us to take advantage of the new induction principle). -
#11772 fixes a bug in the optimized and unsafe implementation of
Array.foldlM. -
#11774 fixes a mismatch between the behavior of
foldlMandfoldlMUnsafein the three array types. This mismatch is only exposed when manually specifying astopvalue greater than the size of the array and only exploitable throughnative_decide. -
#11779 fixes an oversight in the initial #11772 PR.
-
#11784 just adds an optional start position argument to
PersistentArray.forM -
#11789 makes the
FinitenessRelationstructure, which is helpful when proving the finiteness of iterators, part of the public API. Previously, it was marked internal and experimental. -
#11794 implements the function
getMaxFVar?for implementingSymMprimitives. -
#11834 adds
num?parameter tomkPatternFromTheoremto control how many leading quantifiers are stripped when creating a pattern. This enables matching theorems where only some quantifiers should be converted to pattern variables. -
#11848 fixes a bug at
Name.beqreported by gasstationcodemanager@gmail.com -
#11852 changes the definition of the iterator combinators
takeWhileManddropWhileMso that they useMonadAttach. This is only relevant in rare cases, but makes it sometimes possible to prove such combinators finite when the finiteness depends on properties of the monadic predicate. -
#11901 adds
gcd_left_commlemmas for bothNatandInt:-
Nat.gcd_left_comm:gcd m (gcd n k) = gcd n (gcd m k) -
Int.gcd_left_comm:gcd a (gcd b c) = gcd b (gcd a c)
-
-
#11905 provides a
Decidableinstance forNat.isPowerOfTwobased on the formula(n ≠ 0) ∧ (n &&& (n - 1)) = 0. -
#11907 implements
PersistentHashMap.findKeyDandPersistentHashSet.findD. The motivation is avoid two memory allocations (Prod.mkandOption.some) when the collections contains the key. -
#11945 changes the runtime implementation of the
Decidable (xs = #[])andDecidable (#[] = xs)instances to useArray.isEmpty. Previously,decide (xs = #[])would first convertxsinto a list and then compare it againstList.nil. -
#11979 adds
suggest_forannotations such thatInt*.toNatClampis suggested forInt*.toNat. -
#11989 removes a leftover
examplefromsrc/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Lemmas/Operations/Clz.lean. -
#11993 adds
grindannotations to the lemmas aboutSubarrayandListSlice. -
#12058 implements iteration over ranges for
FinandChar. -
#12139 adds
«term_⁻¹»to therecommended_spellingforinv, matching the pattern used by all other operators which include both the function and the syntax in their spelling lists.
Tactics
-
#11664 adds support for
Nat.castingrind linarith. It now usesGrind.OrderedRing.natCast_nonneg. Example:open Lean Grind Std attribute [instance] Semiring.natCast variable [Lean.Grind.CommRing R] [LE R] [LT R] [LawfulOrderLT R] [IsLinearOrder R] [OrderedRing R] example (a : Nat) : 0 ≤ (a : R) := by grind example (a b : Nat) : 0 ≤ (a : R) + (b : R) := by grind
-
#11677 adds basic support for equality propagation in
grind linarithfor theIntModulecase. This covers only the basic case. See note in the code. We remark this feature is irrelevant forCommRingsincegrind ringalready has much better support for equality propagation. -
#11678 fixes a bug in
registerNonlinearOccsAtused to implementgrind lia. This issue was originally reported at: https://leanprover.zulipchat.com/#narrow/channel/113489-new-members/topic/Weirdness.20with.20cutsat/near/562099515 -
#11691 fixes
grindto support dot notation on declarations in the lemma list. -
#11700 adds a link to the
grinddocstring. The link directs users to the section describinggrindin the reference manual. -
#11712 avoids invoking TC synthesis and other inference mechanisms in the simprocs of
bv_decide. This can give significant speedups on problems that pressure these simprocs. -
#11717 improves the performance of
bv_decide's rewriter on large problems. -
#11736 fixes an issue where
exact?would not suggest private declarations defined in the current module. -
#11739 turns even more commonly used
bv_decidetheorems that require unification into fast simprocs using syntactic equality. This pushes the overall performance across sage/app7 to <= 1min10s for every problem. -
#11749 fixes a bug in the function
selectNextSplit?used ingrind. It was incorrectly computing the generation of each candidate. -
#11758 improves support for nonstandard
Int/Natinstances ingrindandsimp +arith. -
#11765 implements user-defined
grindattributes. They are useful for users that want to implement tactics using thegrindinfrastructure (e.g.,progress*in Aeneas). Newgrindattributes are declared using the commandregister_grind_attr my_grind
The command is similar to
register_simp_attr. Recall that similar toregister_simp_attr, the new attribute cannot be used in the same file it is declared.opaque f : Nat → Nat opaque g : Nat → Nat @[my_grind] theorem fax : f (f x) = f x := sorry example theorem fax2 : f (f (f x)) = f x := by fail_if_success grind grind [my_grind]
-
#11769 uses the new support for user-defined
grindattributes to implement the default[grind]attribute. -
#11770 implements support for user-defined attributes at
grind_pattern. After declaring agrindattribute withregister_grind_attr my_grind, one can write:grind_pattern [my_grind] fg => g (f x)
-
#11776 adds the attributes
[grind norm]and[grind unfold]for controlling thegrindnormalizer/preprocessor. -
#11785 disables closed term extraction in the reflection terms used by
bv_decide. These terms do not profit at all from closed term extraction but can in practice cause thousands of new closed term declarations which in turn slows down the compiler. -
#11787 adds support for incrementally processing local declarations in
grind. Instead of processing all hypotheses at once during goal initialization,grindnow tracks which local declarations have been processed viaGoal.nextDeclIdxand provides APIs to process new hypotheses incrementally. This feature will be used by the newSymMmonad for efficient symbolic simulation. -
#11788 introduces
SymM, a new monad for implementing symbolic simulators (e.g., verification condition generators) in Lean. The monad addresses performance issues found in symbolic simulators built on top of user-facing tactics likeapplyandintros. -
#11792 adds
isDebugEnabledfor checking whethergrind.debugis set totruewhengrindwas initialized. -
#11793 adds functions for creating maximally shared terms from maximally shared terms. It is more efficient than creating an expression and then invoking
shareCommon. We are going to use these functions for implementing the symbolic simulation primitives. -
#11797 simplifies
AlphaShareCommon.Stateby separating the persistent and transient parts of the state. -
#11800 adds the function
Sym.replaceS, which is similar toreplace_fnavailable in the kernel but assumes the input is maximally shared and ensures the output is also maximally shared. The PR also generalizes theAlphaShareBuilderAPI. -
#11802 adds the function
Sym.instantiateSand its variants, which are similar toExpr.instantiatebut assumes the input is maximally shared and ensures the output is also maximally shared. -
#11803 implements
intro(and its variants) forSymM. These versions do not use reduction or infer types, and ensure expressions are maximally shared. -
#11806 refactors the
Goaltype used ingrind. The new representation allows multiple goals with different metavariables to share the sameGoalState. This is useful for automation such as symbolic simulator, where applying theorems create multiple goals that inherit the same E-graph, congruence closure and solvers state, and other accumulated facts. -
#11810 adds a new transparency mode
.nonein which no definitions are unfolded. -
#11813 introduces a fast pattern matching and unification module for the symbolic simulation framework (
Sym). The design prioritizes performance by using a two-phase approach:Phase 1 (Syntactic Matching)
-
Patterns use de Bruijn indices for expression variables and renamed level params (
_uvar.0,_uvar.1, ...) for universe variables -
Matching is purely structural after reducible definitions are unfolded during preprocessing
-
Universe levels treat
maxandimaxas uninterpreted functions (no AC reasoning) -
Binders and term metavariables are deferred to Phase 2
Phase 2 (Pending Constraints)
-
Handles binders (Miller patterns) and metavariable unification
-
Converts remaining de Bruijn variables to metavariables
-
Falls back to
isDefEqwhen necessary
-
-
#11814 implements
instantiateRevBetaS, which is similar toinstantiateRevSbut beta-reduces nested applications whose function becomes a lambda after substitution. -
#11815 optimizes pattern matching by skipping proof and instance arguments during Phase 1 (syntactic matching).
-
#11819 adds some basic infrastructure for a structural (and cheaper)
isDefEqpredicate for pattern matching and unification inSym. -
#11820 adds optimized
abstractFVarsandabstractFVarsRangefor converting free variables to de Bruijn indices during pattern matching/unification. -
#11824 implements
isDefEqS, a lightweight structural definitional equality for the symbolic simulation framework. Unlike the fullisDefEq, it avoids expensive operations while still supporting Miller pattern unification. -
#11825 completes the new pattern matching and unification procedures for the symbolic simulation framework using a two-phase approach.
-
#11833 fixes a few typos, adds missing docstrings, and adds a (simple) missing optimization.
-
#11837 adds
BackwardRulefor efficient goal transformation via backward chaining inSymM. -
#11847 adds a new
solverModefield tobv_decide's configuration, allowing users to configure the SAT solver for different kinds of workloads. -
#11849 fixes missing zetaDelta support at the pattern matching/unification procedure in the new Sym framework.
-
#11850 fixes a bug in the new pattern matching procedure for the Sym framework. It was not correctly handling assigned metavariables during pattern matching.
-
#11851 fixes
Sym/Intro.leansupport forhave-declarations. -
#11856 adds the basic infrastructure for the structural simplifier used by the symbolic simulation (
Sym) framework. -
#11857 adds an incremental variant of
shareCommonfor expressions constructed from already-shared subterms. We use this when an expressionewas produced by a Lean API (e.g.,inferType,mkApp4) that does not preserve maximal sharing, but the inputs to that API were already maximally shared. UnlikeshareCommon, this function does not use a localStd.HashMap ExprPtr Exprto track visited nodes. This is more efficient when the number of new (unshared) nodes is small, which is the common case when wrapping API calls that build a few constructor nodes around shared inputs. -
#11858 changes
bv_decide's heuristic for what kinds of structures to split on to also allow splitting on structures where the fields have dependently typed widths. For example:structure Byte (w : Nat) where /-- A two's complement integer value of width `w`. -/ val : BitVec w /-- A per-bit poison mask of width `w`. -/ poison : BitVec w
This is to allow handling situations such as
(x : Byte 8)where the width becomes concrete after splitting is done. -
#11860 adds
CongrInfoanalysis for function applications in the symbolic simulator framework.CongrInfodetermines how to build congruence proofs for rewriting subterms efficiently, categorizing functions into:-
none: no arguments can be rewritten (e.g., proofs) -
fixedPrefix: common case where implicit/instance arguments form a fixed prefix and explicit arguments can be rewritten (e.g.,HAdd.hAdd,Eq) -
interlaced: rewritable and non-rewritable arguments alternate (e.g.,HEq) -
congrTheorem: uses auto-generated congruence theorems for functions with dependent proof arguments (e.g.,Array.eraseIdx)
-
-
#11866 implements the core simplification loop for the
Symframework, with efficient congruence-based argument rewriting. -
#11868 implements
Sym.Simp.Theorem.rewrite?for rewriting terms using equational theorems inSym. -
#11869 adds configuration flag
Meta.Context.cacheInferType. You can use it to disable theinferTypecache atMetaM. We use this flag to implementSymMbecause it has its own cache based on pointer equality. -
#11878 documents assumptions made by the symbolic simulation framework regarding structural matching and definitional equality.
-
#11880 adds a
with_unfolding_nonetactic that sets the transparency mode to.none, in which no definitions are unfolded. This complements the existingwith_unfolding_alltactic and provides tactic-level access to theTransparencyMode.noneadded in https://github.com/leanprover/lean4/pull/11810. -
#11881 fixes an issue where
grindfailed to provef ≠ 0fromf * r ≠ 0when usingLean.Grind.CommSemiring, but succeeded withLean.Grind.Semiring. -
#11884 adds discrimination tree support for the symbolic simulation framework. The new
DiscrTree.leanmodule convertsPatternvalues into discrimination tree keys, treating proof/instance arguments and pattern variables as wildcards (Key.star). Motivation: efficient pattern retrieval during rewriting. -
#11886 adds
getMatchandgetMatchWithExtrafor retrieving patterns from discrimination trees in the symbolic simulation framework. The PR also adds usesDiscrTreeto implement indexing inSym.simp. -
#11888 refactors
Sym.simpto make it more general and customizable. It also moves the code to its own subdirectoryMeta/Sym/Simp. -
#11889 improves the discrimination tree retrieval performance used by
Sym.simp. -
#11890 ensures that
Sym.simpchecks thresholds for maximum recursion depth and maximum number of steps. It also invokescheckSystem. Additionally, this PR simplifies the main loop. Assigned metavariables andzetaDeltareduction are now handled by installingpre/postmethods. -
#11892 optimizes the construction on congruence proofs in
simp. It uses some of the ideas used inSym.simp. -
#11898 adds support for simplifying lambda expressions in
Sym.simp. It is much more efficient than standard simp for very large lambda expressions with many binders. The key idea is to generate a custom function extensionality theorem for the type of the lambda being simplified. -
#11900 adds a
doneflag to the result returned bySimprocs inSym.simp. -
#11906 tries to minimize the number of expressions created at
AlphaShareCommon. -
#11909 reorganizes the monad hierarchy for symbolic computation in Lean.
-
#11911 minimizes the number of expression allocations performed by
replaceSandinstantiateRevBetaS. -
#11914 factors out the
have-telescope support used insimp, and implements it using theMonadSimpinterface. The goal is to use this nice infrastructure for bothMeta.simpandSym.simp. -
#11918 filters deprecated lemmas from
exact?andrw?suggestions. -
#11920 implements support for simplifying
havetelescopes inSym.simp. -
#11923 adds a new option to the function
simpHaveTelescopein which thehavetelescope is simplified in two passes:-
In the first pass, only the values and the body are simplified.
-
In the second pass, unused declarations are eliminated.
-
-
#11932 eliminates super-linear kernel type checking overhead when simplifying lambda expressions. I improved the proof term produced by
mkFunext. This function is used inSym.simpwhen simplifying lambda expressions. -
#11946 adds a
+localsconfiguration option to thegrindtactic that automatically adds all definitions from the current file as e-match theorems. This provides a convenient alternative to manually adding[local grind]attributes to each definition. In the formgrind? +locals, it is also helpful for discovering which local declarations it may be useful to add[local grind]attributes to. -
#11947 adds a
+localsconfiguration option to thesimp,simp_all, anddsimptactics that automatically adds all definitions from the current file to unfold. -
#11949 adds a new
first_partactic combinator that runs multiple tactics in parallel and returns the first successful result (cancelling the others). -
#11950 implements
simpForallandsimpArrowinSym.simp. -
#11962 fixes library suggestions to include private proof-valued structure fields.
-
#11967 implements a new strategy for simplifying
have-telescopes inSym.simpthat achieves linear kernel type-checking time instead of quadratic. -
#11974 optimizes congruence proof construction in
Sym.simpby avoidinginferTypecalls on expressions that are less likely to be cached. Instead of inferring types of expressions like@HAdd.hAdd Nat Nat Nat instAdd 5, we infer the type of the function prefix@HAdd.hAdd Nat Nat Nat instAddand traverse the forall telescope. -
#11976 adds missing type checking for pattern variables during pattern matching/unification to prevent incorrect matches.
-
#11985 implements support for auto-generated congruence theorems in
Sym.simp, enabling simplification of functions with complex argument dependencies such as proof arguments andDecidableinstances. -
#11999 adds support for simplifying the arguments of over-applied and under-applied function application terms in
Sym.simp, completing the implementation for all three congruence strategies (fixed prefix, interlaced, and congruence theorems). -
#12006 fixes the pretty-printing of the
extract_letstactic. Previously, the pretty-printer would expect a space after theextract_letstactic, when it was followed by another tactic on the same line: for example,extract_lets; exact foowould be changed toextract_lets ; exact foo. -
#12012 implements support for rewrite on over-applied terms in
Sym.simp. Example: rewritingid f ausingid_eq. -
#12031 adds
Sym.Simp.evalGround, a simplification procedure for evaluating ground terms of builtin numeric types. It is designed forSym.simp. -
#12032 adds
Dischargers toSym.simp, and ensures the cached results are consistent. -
#12033 adds support for conditional rewriting rules to
Sym.simp. -
#12035 adds
simpControl, a simproc that handles control-flow expressions such asif-then-else. It simplifies conditions while avoiding unnecessary work on branches that won't be taken. -
#12039 implements
match-expression simplification forSym.simp. -
#12040 adds simprocs for simplifying
condand dependentif-then-elseinSym.simp. -
#12053 adds support for offset terms in
SymM. This is essential for handling equational theorems for functions that pattern match on natural numbers inSym.simp. Without this, it cannot handle simple examples such aspw (a + 2)wherepwpattern matches onn+1. -
#12077 implements simprocs for
StringandChar. It also ensures reducible definitions are unfolded inSymM -
#12096 cleanups temporary metavariables generated when applying rewriting rules in
Sym.simp. -
#12099 ensures
Sym.simpGoaldoes not usemkAppM. It also increases the default number of maximum steps inSym.simp. -
#12100 adds a comparison between
MetaMandSymMfor a benchmark was proposed during the Lean@Google Hackathon. -
#12101 improves the the
Sym.simpAPIs. It is now easier to reuse the simplifier cache between different simplification steps. We use the APIs to improve the benchmark at #12100. -
#12134 adds a new benchmark
shallow_add_sub_cancel.leanthat demonstrates symbolic simulation using a shallow embedding into monadicdonotation, as opposed to the deep embedding approach inadd_sub_cancel.lean. -
#12143 adds an API for building symbolic simulation engines and verification condition generators that leverage
grind. The API wrapsSymoperations to work withgrind'sGoaltype, enabling lightweight symbolic execution while carryinggrindstate for discharge steps. -
#12145 moves the pre-shared commonly used expressions from
GrindMtoSymM. -
#12147 adds a new API for helping users write focused rewrites.
Compiler
-
#11479 enables the specializer to also recursively specialize in some non trivial higher order situations.
-
#11729 internalizes all arguments of Quot.lift during LCNF conversion, preventing panics in certain non trivial programs that use quotients.
-
#11874 improves the performance of
getLineby coalescing the locking of the underlyingFILE*. -
#11916 adds a symbol to the runtime for marking
Arraynon-linearities. This should allow users to spot them more easily in profiles or hunt them down using a debugger. -
#11983 fixes the
floatLetInpass to not move variables in case it could break linearity (owned variables being passed with RC 1). This mostly improves the situation in the parser which previously had many functions that were supposed to be linear in terms ofParserStatebut the compiler made them non-linear. For an example of how this affected parsers:def optionalFn (p : ParserFn) : ParserFn := fun c s => let iniSz := s.stackSize let iniPos := s.pos let s := p c s let s := if s.hasError && s.pos == iniPos then s.restore iniSz iniPos else s s.mkNode nullKind iniSz
previously moved the
let iniSz := ...declaration into thehasErrorbranch. However, this means that at the point of calling the inner parser (p c s), the original statesneeds to have RC>1 because it is used later in thehasErrorbranch, breaking linearity. This fix prevents such moves, keepinginiSzbefore thep c scall. -
#12003 splits up the SCC that the compiler manages into (potentially) multiple ones after performing lambda lifting. This aids both the closed term extractor and the elimDeadBranches pass as they are both negatively influenced when more declarations than required are within one SCC.
-
#12008 ensures that the LCNF simplifier already constant folds decision procedures (
Decidableoperations) in the base phase. -
#12010 fixe a superliniear behavior in the closed subterm extractor.
-
#12123 fixes an issue that may sporadically trigger ASAN to got into a deadlock when running a subprocess through the
IO.Process.spawnframework.
Documentation
-
#11737 replaces
ffi.mdwith links to the corresponding sections of the manual, so we don't have to keep two documents up to date. -
#11912 adds missing docstrings for parts of the iterator library, which removes warnings and empty content in the manual.
-
#12047 makes the automatic first token detection in tactic docs much more robust, in addition to making it work in modules and other contexts where builtin tactics are not in the environment. It also adds the ability to override the tactic's first token as the user-visible name.
-
#12072 enables tactic completion and docs for the
let rectactic, which required a stage0 update after #12047. -
#12093 makes the Verso module docstring API more like the Markdown module docstring API, enabling downstream consumers to use them the same way.
Server
-
#11536 corrects the JSON Schema at
src/lake/schemas/lakefile-toml-schema.jsonto allow the table variant of therequire.gitfield inlakefile.tomlas specified in the reference. -
#11630 improves the performance of autocompletion and fuzzy matching by introducing an ASCII fast path into one of their core loops and making Char.toLower/toUpper more efficient.
-
#12000 fixes an issue where go-to-definition would jump to the wrong location in presence of async theorems.
-
#12004 allows 'Go to Definition' to look through reducible definition when looking for typeclass instance projections.
-
#12046 fixes a bug where the unknown identifier code actions were broken in NeoVim due to the language server not properly setting the
data?field for all code action items that it yields. -
#12119 fixes the call hierarchy for
wheredeclarations under the module system
Lake
-
#11683 fixes an inconsistency in the way Lake and Lean view the transitivity of a
meta import. Lake now works as Lean expects and includes the meta segment of all transitive imports of ameta importin its transitive trace. -
#11859 removes the need to write
.ofNatfor numeric options inlakefile.lean. Note thatlake translate-configincorrectly assumed this was already legal in earlier revisions. -
#11921 adds
lake shakeas a built-in Lake command, moving the shake functionality fromscript/Shake.leaninto the Lake CLI. -
#12034 changes the default of
enableArtifactCacheto use the workspace'senableArtifactCachesetting if the package is a dependency andLAKE_ARTIFACT_CACHEis not set. This means that dependencies of a project withenableArtifactCacheset will also, by default, use Lake's local artifact cache. -
#12037 fixes two Lake cache issues: a bug where a failed upload would not produce an error and a mistake in the
--wfailchecks of the cache commands. -
#12076 adds additional debugging information to a run of
lake build --no-buildvia a.nobuildtrace file. When a build fails due to needing a rebuild, Lake emits the new expected trace next as.nobuildfile next to the build's old.trace. The inputs recorded in these files can then be compared to debug what caused the mismatch. -
#12086 fixes a bug where a
lake build --no-buildwould exit with code3if the optional job to fetch a GitHub or Reservoir release for a package failed (even if nothing else needed rebuilding). -
#12105 fixes the
lake queryoutput for targets which produce anArrayorListof a value with a customQueryTextorQueryJsoninstance (e.g.,depsandtransDeps). -
#12112 revives the ability to specify modules in dependencies via the basic
+modtarget key.
Other
-
#11727 adds a Python script that helps find which commit introduced a behavior change in Lean. It supports multiple bisection modes and automatically downloads CI artifacts when available.
-
#11735 adds a standalone script to download pre-built CI artifacts from GitHub Actions. This allows us to quickly switch commits without rebuilding.
-
#11887 makes the external checker lean4checker available as the existing
leancheckerbinary already known to elan, allowing for out-of-the-box access to it. -
#12121 wraps info trees produced by the
leanVerso docstring codeblock in a context info node.
Ffi
-
#12098 removes the requirement that libraries compiled against the lean headers must use
-fwrapv.