Lean 4.27.0-rc1 (2025-12-14)
For this release, 372 changes landed. In addition to the 118 feature additions and 71 fixes listed below there were 28 refactoring changes, 13 documentation improvements, 25 performance improvements, 6 improvements to the test suite and 111 other changes.
Language
-
#7965 lets recursive functions defined by well-founded recursion use a different
fixfunction when the termination measure is of typeNat. This fix-point operator use structural recursion on “fuel”, initialized by the given measure, and is thus reasonable to reduce, e.g. inby decideproofs. -
#11196 avoids match splitter calculation from testing all quadratically many pairs of alternatives for overlaps, by keeping track of possible overlaps during matcher calculation, storing that information in the
MatcherInfo, and using that during matcher calculation. -
#11200 changes how sparse case expressions represent the none-of-the-above information. Instead of of many
x.ctorIdx ≠ ihypotheses, it introduces a singleNat.hasNotBit mask x.ctorIdxhypothesis which compresses that information into a bitmask. This avoids a quadratic overhead during splitter generation, where all n assumptions would be refined through.substand.casesconstructions for all n assumption of the splitter alternative. -
#11221 lets
realizeConstusewithDeclNameForAuxNamingso that auxilary definitions created there get non-clashing names. -
#11222 implements
elabToSyntaxfor creating scoped syntaxs : Syntaxfor an arbitrary elaboratorel : Option Expr -> TermElabM Exprsuch thatelabTerm s = el. -
#11236 extracts two modules from
Match.MatchEqs, in preparation of #11220 and to use the module system to draw clear boundaries between concerns here. -
#11239 adds a
Unitassumption to alternatives of the splitter that would otherwise not have arguments. This fixes #11211. -
#11245 improves the error message encountered in the case of a type class instance resolution failure, and adds an error explanation that discusses the common new-user case of binary operation overloading and points to the
trace.Meta.synthInstanceoption for advanced debugging. -
#11256 replaces
MatcherInfo.numAltParamswith a more detailed data structure that allows us, in particular, to distinguish between an alternative for a constructor with aUnitfield and the alternative for a nullary constructor, where an artificialUnitargument is introduced. -
#11261 continues the homogenization between matchers and splitters, following up on #11256. In particular it removes the ambiguity whether
numParamsincludes thediscrEqnsor not. -
#11269 adds support for decidable equality of empty lists and empty arrays. Decidable equality for lists and arrays is suitably modified so that all diamonds are definitionally equal.
-
#11292 adds intersection operation on
ExtDTreeMap/ExtTreeMap/ExtTreeSetand proves several lemmas about it. -
#11301 allows setting reducibilityCoreExt in async contexts (e.g. when using
mkSparseCasesOnin a realizable definition) -
#11302 renames the CTests tests to use filenames as test names. So instead of
2080 - leanruntest_issue5767.lean (Failed)
we get
2080 - tests/lean/run/issue5767.lean (Failed)
which allows Ctrl-Click’ing on them in the VSCode terminal.
-
#11303 renames rename wrongly named
backwards.options tobackward. -
#11304 documents that
backward.*options are only temporary migration aids and may disappear without further notice after 6 months after their introduction. Users are kindly asked to report if they rely on these options. -
#11305 removes the
groupfield from option descriptions. It is unused, does not have a clear meaning and often matches the first component of the option name. -
#11307 removes all code that sets the
Option.Decl.groupfield, which is unused and has no clearly documented meaning. -
#11325 adds
CoreM.toIO', the analogue ofCoreM.toIOdropping the state from the return type, and similarly forTermElabM.toIO'andMetaM.toIO'. -
#11333 adds infrastructure for parallel execution across Lean's tactic monads.
-
#11338 upstreams the
with_weak_namespacecommand from Mathlib:with_weak_namespace <id> <cmd>changes the current namespace to<id>for the duration of executing command<cmd>, without causing scoped things to go out of scope. This is in preparation for upstreaming thescoped[Foo.Bar]syntax from Mathlib, which will be useful now that we are addinggrindannotations in scopes. -
#11346 modifies the error message for type synthesis failure for the case where the type class in question is potentially derivable using a
derivingcommand. Also changes the error explanation for type class instance synthesis failure with an illustration of this pattern. -
#11347 adds a focused error explanation aimed at the case where someone tries to use Natural-Numbers-Game-style
inductionproofs directly in Lean, where such proofs are not syntactically valid. -
#11353 applies beta reduction to specialization keys, allowing us to reuse specializations in more situations.
-
#11379 sets
@[macro_inline]on the (trivial).ctorIdxfor inductive types with one constructor, to reduce the number of symbols generated by the compiler. -
#11385 lets implicit instance names avoid name clashes with private declarations. This fixes #10329.
-
#11408 adds a difference operation on
ExtDTreeMap/ExtTreeMap/TreeSetand proves several lemmas about it. -
#11422 uses a kernel-reduction optimized variant of Mon.mul in grind.
-
#11425 changes
Lean.Order.CCPOand.CompleteLatticeto carry a Prop. This avoids theCCPO IOinstance from beingnoncomputable. -
#11432 fixes a typo in the docstring of
#guard_mgs. -
#11453 fixes undefined behavior where
delete(instead ofdelete[]) is called on an object allocated withnew[]. -
#11456 refines several error error messages, mostly involving invalid use of field notation, generalized field notation, and numeric projection. Provides a new error explanation for field notation.
-
#11463 fixes a panic in
getEqnsFor?when called on matchers generated from match expressions in theorem types. -
#11474 generalizes the
noConfusionconstructions to heterogeneous equalities (assuming propositional equalities between the indices). This lays ground work for better support for applying injection to heterogeneous equalities in grind. -
#11476 adds a
{givenInstance}`C`documentation role that adds an instance ofCto the document's local assumptions. -
#11482 gives suggestions based on the currently-available constants when projecting from an unknown type.
-
#11485 ensures that
Nats in.oleanfiles use a deterministic serialization in the case whereLEAN_USE_GMPis not set. -
#11490 prevents
tryswallowing heartbeat errors from nestedsimpcalls, and more generally ensures theisRuntimeflag is propagated bythrowNestedTacticEx. This prevents the behavior of proofs (especially those usingaesop) being affected by the current recursion depth or heartbeat limit. -
#11492 uses the the helper functions withImplicitBinderInfos and mkArrowN in more places.
-
#11493 makes
Match.MatchEqsa leaf module, to be less restricted in which features we can use there. -
#11502 adds two benchmarks for elaborating match statements of many
Natliterals, one without and one with splitter generation. -
#11508 avoids generating hyps when not needed (i.e. if there is a catch-all so no completeness checking needed) during matching on values.
This tweak was made possible by #11220.
-
#11510 avoids running substCore twice in caseValues.
-
#11511 implements a linter that warns when a deprecated coercion is applied. It also warns when the
Optioncoercion or theSubarray-to-Arraycoercion is used inInitorStd. The linter is currently limited toCoeinstances;CoeFuninstances etc. are not considered. -
#11518 provides an additional hint when the type of an autobound implicit is required to have function type or equality type — this fails, and the existing error message does not address the fact that the source of the error is an unknown identifier that was automatically bound.
-
#11541 adds support for underscores as digit separators in String.toNat?, String.toInt?, and related parsing functions. This makes the string parsing functions consistent with Lean's numeric literal syntax, which already supports underscores for readability (e.g., 100_000_000).
-
#11554 adds
@[suggest_for]annotations to Lean, allowing lean to provide corrections for.everyor.somemethods in place of.allor.anymethods for most default-imported types (arrays, lists, strings, substrings, and subarrays, and vectors). -
#11555 scans the environment for viable replacements for a dotted identifier (like
.zero) and suggests concrete alternatives as replacements. -
#11566 lets the compiler treat per-constructor
noConfusionlike the general one, and moves some more logic closer to no confusion generation. -
#11571 lets
whnfnot consultisNoConfusion, to speed up this hot path a bit. -
#11587 adjusts the new
metakeyword of the experimental module system not to implypartialfor general consistency. -
#11607 makes argument-less tactic invokations of
Std.Dotactics such asmintroemit a proper error message "mintroexpects at least one pattern" instead of claiming thatStd.Tactic.Doneeds to be imported. -
#11611 fixes a
noConfusioncompilation introduced by #11562. -
#11619 allows Lean to present suggestions based on
@[suggest_for]annotations for unknown identifiers without internal dots. (The annotations in #11554 only gave suggestion for dotted identifiers likeArray.every->Array.alland not for bare identifiers likeResult->Exceptorℕ->Nat.) -
#11620 ports Batteries.WF to Init.WFC for executable well-founded fixpoints. It introduces
csimptheorems to replace the recursors and non-executable definitions with executable definitions. -
#11621 causes Lean to search through
@[suggest_for]annotations on certain errors that look like unknown identifiers that got incorrectly autobound. This will correctly identify that a declaration of typeMaybe Stringshould beOption Stringinstead. -
#11624 fixes a SIGFPE crash on x86_64 when evaluating
INT_MIN / -1orINT_MIN % -1for signed integer types. -
#11637 declares the module system as no longer experimental and makes the
experimental.moduleoption a no-op, to be removed. -
#11644 makes
.ctorIdxnot an abbrev; we don't wantgrindto unfold it. -
#11645 fixes the docstring of
propagateForallPropUp. It was copy’n’pasta before. -
#11652 teaches
grindhow to reduce.ctorIdxapplied to constructors. It can also handle tasks likexs ≍ Vec.cons x xs' → xs.ctorIdx = 1
thanks to a
.ctorIdx.hinjtheorem (generated on demand). -
#11657 improves upon #11652 by keeping the kernel-reduction-optimized definition.
Library
-
#8406 adds lemmas of the form
getElem_swapIfInBounds*and deprecatesgetElem_swap'. -
#9302 modifies
Option.instDecidableEqandOption.decidableEqNoneso that the latter can be made into a global instance without causing diamonds. It also addsOption.decidabeNoneEq. -
#10204 changes the interface of the
ForIn,ForIn', andForMtypeclasses to not take aMonad mparameter. This is a breaking change for most downstreaminstances, which will will now need to assume[Monad m]. -
#10945 adds
Std.Tricho r, a typeclass for relations which identifies them as trichotomous. This is preferred toStd.Antisymm (¬ r · ·)in all cases (which it is equivalent to). -
#11038 introduces a new fixpoint combinator,
WellFounded.extrinsicFix. A termination proof, if provided at all, can be given extrinsically, i.e., looking at the term from the outside, and is only required if one intends to formally verify the behavior of the fixpoint. The new combinator is then applied to the iterator API. Consumers such astoListorForInno longer require a proof that the underlying iterator is finite. If one wants to ensure the termination of them intrinsically, there are strictly terminating variants available as, for example,it.ensureTermination.toListinstead ofit.toList. -
#11112 adds intersection operation on
DHashMap/HashMap/HashSetand provides several lemmas about its behaviour. -
#11141 provides a polymorphic
ForIninstance for slices and an MPLspeclemma for the iteration over slices usingfor ... in. It also provides a version specialized toSubarray. -
#11165 provides intersection on
DTreeMap/TreeMap/TreeSetand provides several lemmas about it. -
#11178 provides more lemmas about
SubarrayandListSliceand it also adds support for subslices of these two types of slices. -
#11180 redefines
String.takeand variants to operate onString.Slice. While previously functions returning a substring of the input sometimes returnedStringand sometimes returnedSubstring.Raw, they now uniformly returnString.Slice. -
#11212 adds support for difference operation for
DHashMap/HashMap/HashSetand proves several lemmas about it. -
#11218 renames
String.offsetOfPostoString.Pos.Raw.offsetOfPosto align with the otherString.Pos.Rawoperations. -
#11222 implements
elabToSyntaxfor creating scoped syntaxs : Syntaxfor an arbitrary elaboratorel : Option Expr -> TermElabM Exprsuch thatelabTerm s = el. -
#11223 adds missing lemmas relating
emptyWithCapacity/emptyandtoList/keys/valuesforDHashMap/HashMap/HashSet. -
#11231 adds several lemmas that relate
getMin/getMin?/getMin!/getMinDand insertion to the empty (D)TreeMap/TreeSet and their extensional variants. -
#11232 deprecates
String.toSubstringin favor ofString.toRawSubstring(cf. #11154). -
#11235 registers a node kind for
Lean.Parser.Term.elabToSyntaxin order to support theLean.Elab.Term.elabToSyntaxfunctionality without registering a dedicated parser for user-accessible syntax. -
#11237 fixes the error thrown by
UInt64.fromJson?andUSize.fromJson?to use the missings!. -
#11240 renames
String.ValidPostoString.Pos,String.endValidPostoString.endPosandString.startValidPostoString.startPos. -
#11241 provides intersection operation for
ExtDHashMap/ExtHashMap/ExtHashSetand proves several lemmas about it. -
#11242 significantly changes the signature of the
ToIteratortype class. The obtained iterators' state is no longer dependently typed and is anoutParaminstead of being bundled inside the class. Among other benefits,simpcan now rewrite inside ofSlice.toListandSlice.toArray. The downside is that we lose flexibility. For example, the former combinator-based implementation ofSubarray's iterators is no longer feasible because the states are dependently typed. Therefore, this PR provides a hand-written iterator forSubarray, which does not require a dependently typed state and is faster than the previous one. -
#11243 adds
ofArraytoDHashMap/HashMap/HashSetand proves a simp lemma allowing to rewriteofArraytoofList. -
#11250 introduces a function
String.splitwhich is based onString.Slice.splitand therefore supports all pattern types and returns aStd.Iter String.Slice. -
#11255 reduces the allocations when using string patterns. In particular
startsWith,dropPrefix?,endsWith,dropSuffix?are optimized. -
#11263 fixes several memory leaks in the new
StringAPI. -
#11266 adds
BEqinstance forDHashMap/HashMap/HashSetand their extensional variants and proves lemmas relating it to the equivalence of hashmaps/equality of extensional variants. -
#11267 renames congruence lemmas for union on
DHashMap/HashMap/HashSet/DTreeMap/TreeMap/TreeSetto fit the convention of being in theEquivnamespace. -
#11276 cleans up the API around
String.findand moves it uniformly to the new position typesString.ValidPosandString.Slice.Pos -
#11281 adds a few deprecations for functions that never existed but that are still helpful for people migrating their code post-#11180.
-
#11282 adds the alias
String.Slice.anyforString.Slice.contains. -
#11285 adds
Std.Slice.Patterninstances forp : Char -> Propas long asDecidablePred p, to allow things like"hello".dropWhile (· = 'h'). -
#11286 adds a function
String.Slice.length, with the following deprecation string: There is no constant-time length function on slices. Uses.positions.countinstead, orisEmptyif you only need to know whether the slice is empty. -
#11289 redefines
String.foldl,String.isNatto use theirString.Slicecounterparts. -
#11290 renames
String.replaceStartEndtoString.slice,String.replaceStarttoString.sliceFrom, andString.replaceEndtoString.sliceTo, and similar for the corresponding functions onString.Slice. -
#11299 add many
@[grind]annotations forFin, and updates the tests. -
#11308 redefines
frontandbackonStringto go throughString.Sliceand adds the newStringfunctionsfront?,back?,positions,chars,revPositions,revChars,byteIterator,revBytes,lines. -
#11316 adds
grind_pattern Exists.choose_spec => P.choose. -
#11317 adds
grind_pattern Subtype.property => self.val. -
#11321 provides specialized lemmas about
Natranges, includingsimpannotations and induction principles for proving properties for all ranges. -
#11327 adds two lemmas to prove
a / c < b / c. -
#11341 adds a coercion from
StringtoString.Slice. -
#11343 renames
String.bytestoString.toByteArray. -
#11354 adds simple lemmas that show that searching from a position in a string returns something that is at least that position.
-
#11357 updates the
foldr,all,anyandcontainsfunctions onStringto be defined in terms of theirString.Slicecounterparts. -
#11358 adds
String.Slice.toInt?and variants. -
#11376 aims to improve the performance of
String.contains,String.find, etc. when using patterns of typeCharorChar -> Boolby moving the needle out of the iterator state and thus working around missing unboxing in the compiler. -
#11380 renames
String.Slice.Pos.ofSlicetoString.Pos.ofToSliceto adhere with the (yet-to-be documented) naming convention for mapping positions to positions. It then adds several new functions so that for every way to construct a slice from a string and slice, there are now functions for mapping positions forwards and backwards along this construction. -
#11384 adds the necessary instances for
grindto reason aboutString.Pos.Raw,String.PosandString.Slice.Pos. -
#11399 adds support for the difference operation for
ExtDHashMap/ExtHashMap/ExtHashSetand proves several lemmas about it. -
#11404 adds BEq instance for
DTreeMap/TreeMap/TreeSetand their extensional variants and proves lemmas relating it to the equivalence of hashmaps/equality of extensional variants. -
#11407 adds the difference operation on
DTreeMap/TreeMap/TreeSetand proves several lemmas about it. -
#11421 adds decidable equality to
DHashMap/HashMap/HashSetand their extensional variants. -
#11439 performs minor maintenance on the String API
-
#11448 moves the
Inhabitedinstances in constantDTreeMap(and related) queries, such asConst.get!, where theInhabitedinstance can be provided before proving a key. -
#11452 adds lemmas stating that if a get operation returns a value, then the queried key must be contained in the collection. These lemmas are added for HashMap and TreeMap-based collections, with a similar lemma also added for
Init.getElem. -
#11465 fixes various typos across the codebase in documentation and comments.
-
#11503 marks
Char -> Boolpatterns as default instances for string search. This means that things like" ".find (·.isWhitespace)can now be elaborated without error. -
#11521 fixes a segmentation fault that was triggered when initializing a new timer and a reset was called at the same time.
-
#11527 adds decidable equality to
DTreeMap/TreeMap/TreeSetand their extensional variants. -
#11528 adds lemmas relating
minKey?andmin?on the keys list for allDTreeMapand other containers derived from it. -
#11542 removes
@[grind =]fromList.countP_eq_length_filterandArray.countP_eq_size_filter, as users reported this was problematic. -
#11548 adds
Lean.ToJsonandLean.FromJsoninstances forString.Slice. -
#11565 adds lemmas that relate
insert/insertIfNewandtoListonDTreeMap/DHashMap-derived containers. -
#11574 adds a lemma that the cast of a natural number into any ordered ring is non-negative. We can't annotate this directly for
grind, but will probably add this togrind's linarith interrnals. -
#11578 refactors the usage of
getoperation onHashMap/TreeMap/ExtHashMap/ExtTreeMaptogetEleminstace. -
#11591 adds missing lemmas about how
ReaderT.run,OptionT.run,StateT.run, andExceptT.runinteract withMonadControloperations. -
#11596 adds
@[suggest_for ℤ]onIntand@[suggest_for ℚ]onRat, following the pattern established by@[suggest_for ℕ]onNatin #11554. -
#11600 adds a few lemmas about
EStateM.runon basic operations. -
#11625 adds
@[expose]todecidable_of_boolso that proofs-by-decideelsewhere that reduce todecidable_of_boolcontinue to reduce. -
#11654 updates the
grinddocstring. It was still mentioningcutsatwhich has been renamed tolia. This issue was reported during ItaLean.
Tactics
-
#11226 finally removes the old
grindframeworkSearchM. It has been replaced with the newActionframework. -
#11244 fixes minor issues in
grind. In preparation for addinggrind -revert. -
#11247 fixes an issue in the
grindpreprocessor.simpmay introduce assigned (universe) metavariables (e.g., when performing zeta-reduction). -
#11248 implements the option
revert, which is set tofalseby default. To recover the oldgrindbehavior, you should usegrind +revert. Previously,grindused theRevSimpIntroidiom, i.e., it would revert all hypotheses and then re-introduce them while simplifying and applying eagercases. This idiom created several problems:-
Users reported that
grindwould include unnecessary parameters. See here. -
Unnecessary section variables were also being introduced. See the new test contributed by Sebastian Graf.
-
Finally, it prevented us from supporting arbitrary parameters as we do in
simp. Insimp, I implemented a mechanism that simulates local universe-polymorphic theorems, but this approach could not be used ingrindbecause there is no mechanism for reverting (and re-introducing) local universe-polymorphic theorems. Adding such a mechanism would require substantial work: I would need to modify the local context object. I considered maintaining a substitution from the original variables to the new ones, but this is also tricky, because the mapping would have to be stored in thegrindgoal objects, and it is not just a simple mapping. After reverting everything, I would need to keep a sequence of original variables that must be added to the mapping as we re-introduce them, but eager case splits complicate this quite a bit. The whole approach felt overly messy.
-
-
#11265 marks the automatically generated
sizeOftheorems asgrindtheorems. -
#11268 implements support for arbitrary
grindparameters. The feature is similar to the one available insimp, where a proof term is treated as a local universe-polymorphic lemma. This feature relies ongrind -revert(see #11248). For example, users can now write:def snd (p : α × β) : β := p.2 theorem snd_eq (a : α) (b : β) : snd (a, b) = b := rfl
-
#11273 fixes a bug during proof construction in
grind. -
#11295 fixes a bug in the propagation rules for
iteandditeused ingrind. The bug prevented equalities from being propagated to the satellite solvers. Here is an example affected by this issue. -
#11315 fixes an issue affecting
grind -revert. In this mode, assigned metavariables in hypotheses were not being instantiated. This issue was affecting two files in Mathlib. -
#11318 fixes a local declaration internalization in
grindthat was exposed when usinggrind -revert. This bug was affecting agrindproof in Mathlib. -
#11319 improves the support for
Fin ningrindwhennis not a numeral. -
#11323 introduces a new
grindoption,funCC(enabled by default), which extends congruence closure to function-valued equalities. WhenfunCCis enabled,grindtracks equalities of partially applied functions, allowing reasoning steps such as:a : Nat → Nat f : (Nat → Nat) → (Nat → Nat) h : f a = a ⊢ (f a) m = a m
-
#11326 ensures that users can provide
grindproof parameters whose types are notforall-quantified. Examples:opaque f : Nat → Nat axiom le_f (a : Nat) : a ≤ f a
-
#11330 renames the
cutsattactic toliafor better alignment with standard terminology in the theorem proving community. -
#11331 adds support for the
LawfulOfScientificclass ingrind. Examples:open Lean Grind Std variable [LE α] [LT α] [LawfulOrderLT α] [Field α] [OfScientific α] [LawfulOfScientific α] [IsLinearOrder α] [OrderedRing α] example : (2 / 3 : α) ≤ (0.67 : α) := by grind example : (1.2 : α) ≤ (1.21 : α) := by grind example : (2 / 3 : α) ≤ (67 / 100 : α) := by grind example : (1.2345 : α) ≤ (1.2346 : α) := by grind example : (2.3 : α) ≤ (4.5 : α) := by grind example : (2.3 : α) ≤ (5/2 : α) := by grind -
#11332 adds a
grind_annotated "YYYY-MM-DD"command that marks files as manually annotated for grind. -
#11334 adds an explicit normalization layer for ring constraints in the
grind linarithmodule. For example, it will be used to clean up denominators when the ring is a field. -
#11335 enables the syntax
use [ns Foo]andinstantiate only [ns Foo]inside agrindtactic block, and has the effect of activating all grind patterns scoped to that namespace. We can use this to implement specialized tactics usinggrind, but only controlled subsets of theorems. -
#11348 activates the
grind_annotatedcommand inInit.Data.List.Lemmasby removing the TODO comment and uncommenting the command. -
#11350 implements a helper simproc for
grind. It is part of the infrastructure used to cleanup denominators ingrind linarith. -
#11365 enables parallelism in
try?. Currently, we replace theattempt_allstages (there are two, one for builtin tactics includinggrindandsimp_all, and a second one for all user extensions) with parallel versions. We do not (yet?) change the behaviour offirstbased stages. -
#11373 makes the library suggestions extension state available when importing from
modulefiles. -
#11375 adds support for cleaning up denominators in
grind linarithwhen the type is aField. -
#11391 implements new kinds of constraints for the
grind_patterncommand. These constraints allow users to control theorem instantiation ingrind. It requires a manualupdate-stage0because the change affects the.oleanformat, and the PR fails without it. -
#11396 changes
set_library_suggestionsto create an auxiliary definition marked with@[library_suggestions], rather than storingSyntaxdirectly in the environment extension. This enables better persistence and consistency of library suggestions across modules. -
#11405 implements the following
grind_patternconstraints:grind_pattern fax => f x where depth x < 2
-
#11409 implements support for the
grind_patternconstraintsis_valueandis_strict_value. -
#11410 fixes a kernel type mismatch error in grind's denominator cleanup feature. When generating proofs involving inverse numerals (like
2⁻¹), the proof context is compacted to only include variables actually used. This involves renaming variable indices - e.g., if original indices were{0: r, 1: 2⁻¹}and only2⁻¹is used, it gets renamed to index 0. -
#11412 fixes an issue where
grindwould fail after multiplenorm_castcalls with the error "unexpected metadata found during internalization". -
#11428 implements support for guards in
grind_pattern. The new feature provides additional control over theorem instantiation. For example, consider the following monotonicity theorem:opaque f : Nat → Nat theorem fMono : x ≤ y → f x ≤ f y := ...
-
#11429 documents the
grind_patterncommand for manually selecting theorem instantiation patterns, including multi-patterns and the constraint system (=/=,=?=,size,depth,is_ground,is_value,is_strict_value,gen,max_insts,guard,check). -
#11462 adds
solve_by_elimas a fallback in thetry?tactic's simple tactics. Whenrflandassumptionboth fail butsolve_by_elimsucceeds (e.g., for goals requiring hypothesis chaining or backtracking),try?will now suggestsolve_by_elim. -
#11464 improves the error message when no library suggestions engine is registered to recommend importing
Lean.LibrarySuggestions.Defaultfor the built-in engine. -
#11466 removes the "first pass" behavior where
exact?andapply?would trysolve_by_elimon the original goal before doing library search. This simplifies thelibrarySearchAPI and focuses these tactics on their primary purpose: finding library lemmas. -
#11468 adds
+suggestionssupport tosolve_by_elim, following the pattern established bygrind +suggestionsandsimp_all +suggestions. -
#11469 adds
+grindand+try?options toexact?andapply?tactics. -
#11471 fixes an incorrect reducibility setting when using
grindinteractive mode. -
#11480 adds the
grindoptionreducible(default:true). When enabled, definitional equality tests expand only declarations marked as@[reducible]. Usegrind -reducibleto allow expansion of non-reducible declarations during definitional equality tests. This option affects only definitional equality; the canonicalizer and theorem pattern internalization always unfold reducible declarations regardless of this setting. -
#11481 fixes a bug in
grind?. The suggestion using thegrindinteractive mode was dropping the configuration options provided by the user. In the following account, the third suggestion was dropping the-reducibleoption. -
#11484 fixes a bug in the
grindpattern validation. The bug affected type classes that were propositions. -
#11487 adds a heterogeneous version of the constructor injectivity theorems. These theorems are useful for indexed families, and will be used in
grind. -
#11491 implements heterogeneous contructor injectivity in
grind. -
#11494 re-enables star-indexed lemmas as a fallback for
exact?andapply?. -
#11519 marks
Natpower and divisibility theorems forgrind. We use the newgrind_patternconstraints to control theorem instantiation. Examples:example {x m n : Nat} (h : x = 4 ^ (m + 1) * n) : x % 4 = 0 := by grind -
#11520 implements the constraint
not_value xin thegrind_patterncommand. It is the negation of the constraintis_value. -
#11522 implements
grindpropagators forNatoperators that have a simproc associated with them, but do not have any theory solver support. Examples:example (a b : Nat) : a = 3 → b = 6 → a &&& b = 2 := by grind example (a b : Nat) : a = 3 → b = 6 → a ||| b = 7 := by grind example (a b : Nat) : a = 3 → b = 6 → a ^^^ b = 5 := by grind example (a b : Nat) : a = 3 → b = 6 → a <<< b = 192 := by grind example (a b : Nat) : a = 1135 → b = 6 → a >>> b = 17 := by grind
-
#11547 ensures the auxiliary definitions created by
register_try?_tacticare internal implementation details that should not be visible to user-facing linters. -
#11556 adds a
+alloption toexact?andapply?that collects all successful lemmas instead of stopping at the first complete solution. -
#11573 fixes
grindrejecting dot notation terms, mistaking them for local hypotheses. -
#11579 ensures that ground theorems are properly handled as
grindparameters. Additionally,grind [(thm)]andgrind [thm]should be handled the same way. -
#11580 adds a missing
Nat.castmissing normalization rule forgrind. Example:example (n : Nat) : Nat.cast n = n := by grind
-
#11589 improves indexing for
grindpatterns. We now include symbols occurring in nested ground patterns. This important to minimize the number of activated E-match theorems. -
#11593 fixes an issue where
grinddid not display deprecation warnings when deprecated lemmas were used in its argument list. -
#11594 fixes
grind?to include term parameters (like[show P by tac]) in its suggestions. Previously, these were being dropped because term arguments are stored inextraFactsand not tracked via E-matching like named lemmas. -
#11604 fixes how theorems without parameters are handled in
grind. -
#11605 fixes a bug in the internalizer of
a^pterms ingrind linarith. -
#11609 improves the case-split heuristics in
grind. In this PR, we do not increment the number of case splits in the first case. The idea is to leverage non-chronological backtracking: if the first case is solved using a proof that doesn't depend on the case hypothesis, we backtrack and close the original goal directly. In this scenario, the case-split was "free", it didn't contribute to the proof. By not counting it, we allow deeper exploration when case-splits turn out to be irrelevant. The new heuristic addresses the second example in #11545 -
#11613 ensures we apply the ring normalizer to equalities being propagated from the
grindcore module togrind lia. It also ensures we use the safe/managed polynomial functions when normalizing. -
#11615 adds a normalization rule for
Int.subNatNattogrind. -
#11628 adds a few
*normalization rules forSemirings togrind. -
#11629 adds a missing condition in the pattern normalization code used in
grind. It should ignore support ground terms. -
#11635 ensures the pattern normalizer used in
grinddoes violate assumptions made by the gadgetsGrind.genPatternandGrind.getHEqPattern. -
#11638 fixes bitvector literal internalization in
grind. The fix ensures theorems indexed byBitVec.ofNatare properly activated. -
#11639 adds support for
BitVec.ofNatingrind ring. Example:example (x : BitVec 8) : (x - 16#8)*(x + 272#8) = x^2 := by grind
-
#11640 adds support for
BitVec.ofNatingrind lia. Example:example (x y : BitVec 8) : y < 254#8 → x > 2#8 + y → x > 1#8 + y := by grind
-
#11653 adds propagation rules corresponding to the
Semiringnormalization rules introduced in #11628. The new rules apply only to non-commutative semirings, since support for them ingrindis limited. The normalization rules introduced unexpected behavior in Mathlib because they neutralize parameters such asone_mul: any theorem instance associated with such a parameter is reduced toTrueby the normalizer. -
#11656 adds support for
Int.sign,Int.fdiv,Int.tdiv,Int.fmod,Int.tmod, andInt.bmodtogrind. These operations are just preprocessed away. We assume that they are not very common in practice. Examples:example {x y : Int} : y = 0 → (x.fdiv y) = 0 := by grind example {x y : Int} : y = 0 → (x.tdiv y) = 0 := by grind example {x y : Int} : y = 0 → (x.fmod y) = x := by grind example {x y : Int} : y = 1 → (x.fdiv (2 - y)) = x := by grind example {x : Int} : x > 0 → x.sign = 1 := by grind example {x : Int} : x < 0 → x.sign = -1 := by grind example {x y : Int} : x.sign = 0 → x*y = 0 := by grind -
#11658 fixes a bug in the internalization of parametric literals in
grind. That is, literals whose type isBitVec _orFin _. -
#11659 adds
MessageData.withNamingContextwhen generating pattern suggestions at@[grind]. It fixes another issue reported during ItaLean. -
#11660 fixes another theorem activation issue in
grind. -
#11663 fixes the
grindpattern validator. It covers the case where an instance is not tagged with the implicit instance binder. This happens in declarations such asZeroMemClass.zero_mem {S : Type} {M : outParam Type} {inst1 : Zero M} {inst2 : SetLike S M} [self : @ZeroMemClass S M inst1 inst2] (s : S) : 0 ∈ s
Compiler
-
#11082 prevents symbol clashes between (non-
@[export]) definitions from different Lean packages. -
#11185 fixes the
reduceAritycompiler pass to consider over-applications to functions that have their arity reduced. Previously, this pass assumed that the amount of arguments to applications was always the same as the number of parameters in the signature. This is usually true, since the compiler eagerly introduces parameters as long as the return type is a function type, resulting in a function with a return type that isn't a function type. However, for dependent types that sometimes are function types and sometimes not, this assumption is broken, resulting in the additional parameters to be dropped. -
#11210 fixes a bug in the LCNF simplifier unearthed while working on #11078. In some situations caused by
unsafeCast, the simplifier would record incorrect information aboutcases, leading to further bugs down the line. -
#11215 fixes an issue where header nesting levels were properly tracked between, but not within, moduledocs.
-
#11217 fixes fallout of the closure allocator changes in #10982. As far as we know this bug only meaningfully manifests in non default build configurations without mimalloc such as:
cmake --preset release -DUSE_MIMALLOC=OFF -
#11310 makes the specializer (correctly) share more cache keys across invocations, causing us to produce less code bloat.
-
#11340 fixes a miscompilation when encountering projections of non trivial structure types.
-
#11362 accelerates termination of the ElimDeadBranches compiler pass.
-
#11366 sorts the declarations fed into ElimDeadBranches in increasing size. This can improve performance when we are dealing with a lot of iterations.
-
#11381 fixes a bug where the closed term extraction does not respect the implicit invariant of the c emitter to have closed term decls first, other decls second, within an SCC. This bug has not yet been triggered in the wild but was unearthed during work on upcoming modifications of the specializer.
-
#11383 fixes the compilation of structure projections with unboxed arguments marked
extern, adding missingdecinstructions. It led to leaking single allocations when such functions were used as closures or in the interpreter. -
#11388 is a followup of #11381 and enforces the invariants on ordering of closed terms and constants required by the EmitC pass properly by toposorting before saving the declarations into the Environment.
-
#11426 closes #11356.
-
#11445 slightly improves the types involved in creating boxed declarations. Previously the type of the vdecl used for the return was always
tobjwhen returning a boxed scalar. This is not the most precise annotation we can give. -
#11451 adapts the lambda lifter in LCNF to eta contract instead of lambda lift if possible. This prevents the creation of a few hundred unnecessary lambdas across the code base.
-
#11517 implements constant folding for Nat.mul
-
#11525 makes the LCNF simplifier eliminate cases where all alts are
.unreachto just an.unreach. an.unreach -
#11530 introduces the new
tagged_returnattribute. It allows users to markexterndeclarations to be guaranteed to always returntaggedreturn values. Unlike withobjectortobjectthe compiler does not emit reference counting operations for them. In the future information from this attribute will be used for a more powerful analysis to remove reference counts when possible. -
#11576 removes the old ElimDeadBranches pass and shifts the new one past lambda lifting.
-
#11586 allows projections on
taggedvalues in the IR type system.
Documentation
-
#11119 introduces a clarifying note to "undefined identifier" error messages when the undefined identifier is in a syntactic position where autobinding might generally apply, but where and autobinding is disabled. A corresponding note is made in the
lean.unknownIdentifiererror explanation. -
#11364 adds missing docstrings for constants that occur in the reference manual.
-
#11472 adds missing docstrings for the
mkSlicemethods. -
#11550 reviews the docstrings for
Std.Dothat will appear in the Lean reference manual and adds those that were missing. -
#11575 fixes a typo in the docstring of the
casestactic. -
#11595 documents that tests in
tests/lean/run/run with-Dlinter.all=false, and explains how to enable specific linters when testing linter behavior.
Server
-
#11162 reduces the memory consumption of the language server (the watchdog process in particular). In Mathlib, it reduces memory consumption by about 1GB.
-
#11164 ensures that the code action provided on unknown identifiers correctly inserts
publicand/ormetainmodules -
#11577 fixes the tactic framework reporting file progress bar ranges that cover up progress inside tactic blocks nested in tactic combinators. This is a purely visual change, incremental re-elaboration inside supported combinators was not affected.
Lake
-
#11198 fixes an error message in Lake which suggested incorrect lakefile syntax.
-
#11216 ensures that the
textargument ofcomputeArtifactis always provided in Lake code, fixing a hashing bug withbuildArtifactUnlessUpToDatein the process. -
#11270 adds a module resolution procedure to Lake to disambiguate modules that are defined in multiple packages.
-
#11500 adds a workspace-index to the name of the package used by build target. To clarify the distinction between the different uses of a package's name, this PR also deprecates
Package.namefor more use-specific variants (e.g.,Package.keyName,Package.prettyName,Package.origName).
Other
-
#11328 fixes freeing memory accidentally retained for each document version in the language server on certain elaboration workloads. The issue must have existed since 4.18.0.
-
#11437 adds recording functionality such that
shakecan more precisely track whether an import should be preserved solely for itsattributecommands. -
#11496 implements new flags and annotations for
shakefor use in Mathlib:Options: --keep-implied Preserves existing imports that are implied by other imports and thus not technically needed anymore
--keep-prefix If an import
Xwould be replaced in favor of a more specific importX.Y...it implies, preserves the original import instead. More generally, prefers insertingimport Xeven if it was not part of the original imports as long as it was in the original transitive import closure of the current module.--keep-public Preserves all
publicimports to avoid breaking changes for external downstream modules--add-public Adds new imports as
publicif they have been in the original public closure of that module. In other words, public imports will not be removed from a module unless they are unused even in the private scope, and those that are removed will be re-added aspublicin downstream modules even if only needed in the private scope there. Unlike--keep-public, this may introduce breaking changes but will still limit the number of inserted imports.Annotations: The following annotations can be added to Lean files in order to configure the behavior of
shake. Only the substringshake:directly followed by a directive is checked for, so multiple directives can be mixed in one line such as-- shake: keep-downstream, shake: keep-all, and they can be surrounded by arbitrary comments such as-- shake: keep (metaprogram output dependency).-
module -- shake: keep-downstream: Preserves this module in all (current) downstream modules, adding new imports of it if needed. -
module -- shake: keep-all: Preserves all existing imports in this module as is. New imports now needed because of upstream changes may still be added. -
import X -- shake: keep: Preserves this specific import in the current module. The most common use case is to preserve a public import that will be needed in downstream modules to make sense of the output of a metaprogram defined in this module. For example, if a tactic is defined that may synthesize a reference to a theorem when run, there is no way forshaketo detect this by itself and the module of that theorem should be publicly imported and annotated withkeepin the tactic's module.public import X -- shake: keep (metaprogram output dependency) ... elab \"my_tactic\" : tactic => do
... mkConst ``f --
f, defined inX, may appear in the output of this tactic ``` -
-
#11507 optimizes the filesystem accesses during importing for a ~3% win on Linux, potentially more on other platforms.