Lean 4.23.0 (2025-09-15)
For this release, 610 changes landed. In addition to the 95 feature additions and 139 fixes listed below there were 61 refactoring changes, 12 documentation improvements, 71 performance improvements, and 232 other changes.
Highlights
Lean v4.23.0 release brings significant performance improvements, better error messages,
and a plethora of bug fixes, refinements, and consolidations in grind, the compiler, and other components of Lean.
In terms of user experience, noteworthy new features are:
-
Improved 'Go to Definition' navigation (#9040)
-
Using 'Go to Definition' on a type class projection now extracts the specific instances that were involved and provides them as locations to jump to. For example, using 'Go to Definition' on the
toStringoftoString 0yields results forToString.toStringandToString Nat. -
Using 'Go to Definition' on a macro that produces syntax with type class projections now also extracts the specific instances that were involved and provides them as locations to jump to. For example, using 'Go to Definition' on the
+of1 + 1yields results forHAdd.hAdd,HAdd α α αandAdd Nat. -
Using 'Go to Declaration' now provides all the results of 'Go to Definition' in addition to the elaborator and the parser that were involved. For example, using 'Go to Declaration' on the
+of1 + 1yields results forHAdd.hAdd,HAdd α α α,Add Nat,macro_rules | `($x + $y) => ...andinfixl:65 " + " => HAdd.hAdd. -
Using 'Go to Type Definition' on a value with a type that contains multiple constants now provides 'Go to Definition' results for each constant. For example, using 'Go to Type Definition' on
xforx : Array Natyields results forArrayandNat.
-
-
Interactive code-action hints for errors:
-
for "invalid named argument" error, suggest valid argument names (#9315)
-
for "invalid case name" error, suggest valid case names (#9316)
-
for "fields missing" error in structure instances, suggest to insert all the missing fields (#9317)
You can try all of these in the Lean playground.
-
Breaking Changes
-
#9800 improves the delta deriving handler, giving it the ability to process definitions with binders, as well as the ability to recursively unfold definitions. Breaking change: the derived instance's name uses the
instancecommand's name generator, and the new instance is added to the current namespace. -
#9040 improves the 'Go to Definition' UX. Breaking change:
InfoTree.hoverableInfoAt?has been generalized toInfoTree.hoverableInfoAtM?and now takes a generalfilterargument instead of several boolean flags, as was the case before. -
#9594 optimizes
Lean.Name.toString, giving a 10% instruction benefit.Crucially this is a breaking change as the old
Lean.Name.toStringmethod used to support a method for identifying tokens. This method is now available asLean.Name.toStringWithTokenin order to allow for specialization of the (highly common)toStringcode path which sets this function to just returnfalse. -
#9729 introduces a canonical way to endow a type with an order structure. Breaking changes:
-
The requirements of the
lt_of_le_of_lt/le_translemmas forVector,ListandArrayare simplified. They now require anIsLinearOrderinstance. The new requirements are logically equivalent to the old ones, but theIsLinearOrderinstance is not automatically inferred from the smaller typeclasses. -
Hypotheses of type
Std.Total (¬ · < · : α → α → Prop)are replaced with the equivalent classStd.Asymm (· < · : α → α → Prop). Breakage should be limited because there is now an instance that derives the latter from the former. -
In
Init.Data.List.MinMax, multiple theorem signatures are modified, replacing explicit parameters for antisymmetry, totality,min_ex_oretc. with corresponding instance parameters.
-
Language
-
#6732 adds support for the
cleartactic in conversion mode. -
#8666 adjusts the experimental module system to not import the IR of non-
metadeclarations. It does this by replacing such IR with opaque foreign declarations on export and adjusting the new compiler accordingly. -
#8842 fixes the bug that
collectAxiomsdidn't collect axioms referenced by other axioms. One of the results of this bug is that axioms collected from a theorem proved bynative_decidemay not includeLean.trustCompiler. -
#9015 makes
isDefEqdetect more stuck definitional equalities involving smart unfoldings. Specifically, ift =?= defn ?manddefnmatches on its argument, then this equality is stuck on?m. Prior to this change, we would not see this dependency and simply returnfalse. -
#9084 adds
binrel%macros for!=and≠notation defined inInit.Core. This allows the elaborator to insert coercions on both sides of the relation, instead of committing to the type on the left hand side. -
#9090 fixes a bug in
whnfCorewhere it would fail to reduce applications of recursors/auxiliary defs. -
#9097 ensures that
mspecuses the configured transparency setting and makesmvcgenuse default transparency when callingmspec. -
#9099 improves the “expected type mismatch” error message by omitting the type's types when they are defeq, and putting them into separate lines when not.
-
#9103 prevents truncation of
panic!messages containing null bytes. -
#9108 fixes an issue that may have caused inline expressions in messages to be unnecessarily rendered on a separate line.
-
#9113 improves the
grinddoc string and tries to make it more approachable to new user. -
#9130 fixes unexpected occurrences of the
Grind.offsetgadget in ground patterns. See new test -
#9131 adds a
usedLetOnlyparameter toLocalContext.mkLambdaandLocalContext.mkForall, to parallel theMetavarContextversions. -
#9133 adds support for
a^(m+n)in thegrindnormalizer. -
#9143 removes a rather ugly hack in the module system, exposing the bodies of theorems whose type mention
WellFounded. -
#9146 adds "safe" polynomial operations to
grind ring. The use the usual combinators:withIncRecDepthandcheckSystem. -
#9149 generalizes the
a^(m+n)grind normalizer to any semirings. Example:variable [Field R]
-
#9150 adds a missing case in the
toPolyfunction used ingrind. -
#9153 improves the linarith
markVars, and ensures it does not produce spurious issue messages. -
#9168 resolves a defeq diamond, which caused a problem in Mathlib:
import Mathlib
-
#9172 fixes a bug at
matchEqBwdPat. The type may contain pattern variables. -
#9173 fixes an incompatibility in the experimental module system when trying to combine wellfounded recursion with public exposed definitions.
-
#9176 makes
mvcgensplit ifs rather than applying specifications. Doing so fixes a bug reported by Rish. -
#9182 tries to improve the E-matching pattern inference for
grind. That said, we still need better tools for annotating and maintaininggrindannotations in libraries. -
#9184 fixes stealing of
⇓syntax by the new notation for total postconditions by demoting it to non-builtin syntax and scoping it toStd.Do. -
#9191 lets the equation compiler unfold abstracted proofs again if they would otherwise hide recursive calls.
This fixes #8939.
-
#9193 fixes the unexpected kernel projection issue reported by issue #9187
-
#9194 makes the logic and tactics of
Std.Douniverse polymorphic, at the cost of a few definitional properties arising from the switch fromProptoULift Propin the base caseSPred []. -
#9196 implements
forallnormalization using a simproc instead of rewriting rules ingrind. This is the first part of the PR, after update stage0, we must remove the normalization theorems. -
#9200 implements
existsnormalization using a simproc instead of rewriting rules in grind. This is the first part of the PR, after update stage0, we must remove the normalization theorems. -
#9202 extends the
Eqsimproc used ingrind. It covers more cases now. It also adds 3 reducible declarations to the list of declarations to unfold. -
#9214 implements support for local and scoped
grind_patterncommands. -
#9225 improves the
congrtactic so that it can handle function applications with fewer arguments than the arity of the head function. This also fixes a bug wherecongrcould not make progress withSet-valued functions in Mathlib, sinceSetwas being unfolded and making such functions have an apparently higher arity. -
#9228 improves the startup time for
grind ringby generating the required type classes on demand. This optimization is particularly relevant for files that make hundreds of calls togrind, such astests/lean/run/grind_bitvec2.lean. For example, before this change,grindspent 6.87 seconds synthesizing type classes, compared to 3.92 seconds after this PR. -
#9241 ensures that the type class instances used to implement the
ToIntadapter (ingrind cutsat) are generated on demand. -
#9244 improves the instance generation in the
grind linarithmodule. -
#9251 demotes the builtin elaborators for
Std.Do.PostCond.totalandStd.Do.Tripleinto macros, following the DefEq improvements of #9015. -
#9267 optimizes support for
Decidableinstances ingrind. BecauseDecidableis a subsingleton, the canonicalizer no longer wastes time normalizing such instances, a significant performance bottleneck in benchmarks likegrind_bitvec2.lean. In addition, the congruence-closure module now handlesDecidableinstances, and can solve examples such as:example (p q : Prop) (h₁ : Decidable p) (h₂ : Decidable (p ∧ q)) : (p ↔ q) → h₁ ≍ h₂ := by grind
-
#9271 improves the performance of the formula normalizer used in
grind. -
#9287 rewords the "application type mismatch" error message so that the argument and its type precede the application expression.
-
#9293 replaces the
reduceCtorEqsimproc used ingrindby a much more efficient one. The default one use insimpis just overhead because thegrindnormalizer is already normalizing arithmetic. In a separate PR, we will push performance improvements to the defaultreduceCtorEq. -
#9305 uses the
mkCongrSimpForConst?API insimpto reduce the number of times the same congruence lemma is generated. Before this PR,grindwould spend1.5s creating congruence theorems during normalization in thegrind_bitvec2.leanbenchmark. It now spends0.6s. should make an even bigger difference after we merge #9300. -
#9315 adds improves the "invalid named argument" error message in function applications and match patterns by providing clickable hints with valid argument names. In so doing, it also fixes an issue where this error message would erroneously flag valid match-pattern argument names.
-
#9316 adds clickable code-action hints to the "invalid case name" error message.
-
#9317 adds to the "fields missing" error message for structure instance notation a code-action hint that inserts all missing fields.
-
#9324 improves the functions for checking whether two terms are disequal in
grind -
#9325 optimizes the Boolean disequality propagator used in
grind. -
#9326 optimizes
propagateEqUpused ingrind. -
#9340 modifies the encoding from
NattoIntused ingrind cutsat. It is simpler, more extensible, and similar to the genericToInt. After update stage0, we will be able to delete the leftovers. -
#9351 optimizes the
grindpreprocessing steps by skipping steps when the term is already present in the hash-consing table. -
#9358 adds support for generating lattice-theoretic (co)induction proof principles for predicates defined via
mutualblocks usinginductive_fixpoint/coinductive_fixpointconstructs. -
#9367 implements a minor optimization to the
grindpreprocessor. -
#9369 optimizes the
grindpreprocessor by skipping unnecessary steps when possible. -
#9371 fixes an issue that caused some
derivinghandlers to fail when the name of the type being declared matched that of a declaration in an open namespace. -
#9372 fixes a performance issue that occurs when generating equation lemmas for functions that use match-expressions containing several literals. This issue was exposed by #9322 and arises from a combination of factors:
-
Literal values are compiled into a chain of dependent if-then-else expressions.
-
Dependent if-then-else expressions are significantly more expensive to simplify than regular ones.
-
The
splittactic selects a target, splits it, and then invokessimpon the resulting subgoals. Moreover,simptraverses the entire goal bottom-up and does not stop after reaching the target.
-
-
#9385 replaces the
isDefEqtest in thesimpEqsimproc used ingrind. It is too expensive. -
#9386 improves a confusing error message that occurred when attempting to project from a zero-field structure.
-
#9387 adds a hint to the "invalid projection" message suggesting the correct nested projection for expressions of the form
t.nwheretis a tuple andn > 2. -
#9395 fixes a bug at
mkCongrSimpCore?. It fixes the issue reported by @joehendrix at #9388. The fix is just commit: afc4ba617fe2ca5828e0e252558d893d7791d56b. The rest of the PR is just cleaning up the file. -
#9398 avoids the expensive
inferTypecall insimpArith. It also cleans up some of the code and removes anti-patterns. -
#9408 implements a simple optimization: dependent implications are no longer treated as E-matching theorems in
grind. Ingrind_bitvec2.lean, this change saves around 3 seconds, as many dependent implications are generated. Example:∀ (h : i + 1 ≤ w), x.abs.getLsbD i = x.abs[i]
-
#9414 increases the number of cases where
isArrowPropositionreturns a result other than.undef. This function is used to implement theisProofpredicate, which is invoked on every subterm visited bysimp. -
#9421 fixes a bug that caused error explanations to "steal" the Infoview's container in the Lean web editor.
-
#9423 updates the formatting of, and adds explanations for, "unknown identifier" errors as well as "failed to infer type" errors for binders and definitions.
-
#9424 improves the error messages produced by the
splittactic, including suggesting syntax fixes and related tactics with which it might be confused. -
#9443 makes cdot function expansion take hygiene information into account, fixing "parenthesis capturing" errors that can make erroneous cdots trigger cdot expansion in conjunction with macros. For example, given
macro "baz% " t:term : term => `(1 + ($t))
it used to be that
baz% ·would expand to1 + fun x => x, but now the parentheses in($t)do not capture the cdot. We also fix an oversight where cdot function expansion ignored the fact that type ascriptions and tuples were supposed to delimit expansion, and also now the quotation prechecker ignores the identifier inhygieneInfo. (#9491 added the hygiene information to the parenthesis and cdot syntaxes.) -
#9447 ensures that
mvcgennot only tries to close stateful subgoals by assumption, but also pure Lean goals. -
#9448 addresses the lean crash (stack overflow) with nested induction and the generation of the
SizeOfspec lemmas, reported at #9018. -
#9451 adds support in the
mintrotactic for introducinglet/havebinders in stateful targets, akin tointro. This is useful when specifications introduce such let bindings. -
#9454 introduces tactic
mleavethat leaves theSPredproof mode by eta expanding through its abstractions and applying some mild simplifications. This is useful to apply automation such asgrindafterwards. -
#9464 makes
PProdN.reduceProjsalso look for projection functions. Previously, all redexes were created by the functions inPProdN, which used primitive projections. But withmkAdmProjthe projection functions creep in via the types of theadmissible_pprod_fsttheorem. So let's just reduce both of them. -
#9472 fixes another issue at the
congr_simptheorems that was affecting Mathlib. Many thanks to Johan Commelin for creating the mwe. -
#9476 fixes the bridge between
NatandIntingrind cutsat. -
#9479 improves the
evalInt?function, which is used to evaluate configuration parameters from theToInttype class. also adds a newevalNat?function for handling theIsCharPtype class, and introduces a configuration option:grind (exp := <num>)
This option controls the maximum exponent size considered during expression evaluation. Previously,
evalInt?usedwhnf, which could run out of stack space when reducing terms such as2^1024. -
#9480 adds a feature where
structureconstructors can override the inferred binder kinds of the type's parameters. In the following, the(p)binder ontoLpcausespto be an explicit parameter toWithLp.toLp:structure WithLp (p : Nat) (V : Type) where toLp (p) :: ofLp : V
This reflects the syntax of the feature added in #7742 for overriding binder kinds of structure projections. Similarly, only those parameters in the header of the
structuremay be updated; it is an error to try to update binder kinds of parameters included viavariable. -
#9481 fixes a kernel type mismatch that occurs when using
grindon goals containing non-standardOfNat.ofNatterms. For example, in issue #9477, the0in the theoremrange_lowerhas the form:(@OfNat.ofNat (Std.PRange.Bound (Std.PRange.RangeShape.lower (Std.PRange.RangeShape.mk Std.PRange.BoundShape.closed Std.PRange.BoundShape.open)) Nat) (nat_lit 0) (instOfNatNat (nat_lit 0)))
instead of the more standard form:
(@OfNat.ofNat Nat (nat_lit 0) (instOfNatNat (nat_lit 0)))
-
#9487 fixes an incorrect proof term constructed by
grind linarith, as reported in #9485. -
#9491 adds hygiene info to paren/tuple/typeAscription syntaxes, which will be used to implement hygienic cdot function expansion in #9443.
-
#9496 improves the error messages produced by the
set_optioncommand. -
#9500 adds a
HPow \a Int \afield toLean.Grind.Field, and sufficient axioms to connect it to the operations, so that in future we can reason about exponents ingrind. To avoid collisions, we also move theHPow \a Nat \afield inSemiringfrom the extends clause to a field. Finally, we add some failing tests about normalizing exponents. -
#9505 removes vestigial syntax definitions in
Lean.Elab.Tactic.Do.VCGenthat when imported undefine themvcgentactic. Now it should be possible to import Mathlib and still usemvcgen. -
#9506 adds a few missing simp lemmas to
mleave. -
#9507 makes
mvcgenmintrolet/have bindings. -
#9509 surfaces kernel diagnostics even in
example. -
#9512 makes
mframe,mspecandmvcgenrespect hygiene. Inaccessible stateful hypotheses can now be named with a new tacticmrename_ithat works analogously torename_i. -
#9516 ensures that private declarations made inaccessible by the module system are noted in the relevant error messages
-
#9518 ensures previous "is marked as private" messages are still triggered under the module system
-
#9520 corrects the changes to
Lean.Grind.Fieldmade in #9500. -
#9522 uses
withAbstractAtomsto prevent the kernel from accidentally reducing the atoms in the arith normlizer while typechecking. This PR also setsimplicitDefEqProofs := falsein thegrindnormalizer -
#9532 generalizes
Process.outputandProcess.runwith an optionalStringargument that can be piped tostdin. -
#9551 fixes the error position for the "dependent elimination failed" error for the
casestactic. -
#9553 fixes a bug introduced in #7830 where if the cursor is at the indicated position
example (as bs : List Nat) : (as.append bs).length = as.length + bs.length := by induction as with | nil => -- cursor | cons b bs ih =>
then the Infoview would show "no goals" rather than the
nilgoal. The PR also fixes a separate bug where placing the cursor on the next line after theinduction/casestactics like ininduction as with | nil => sorry | cons b bs ih => sorry I -- < cursor
would report the original goal in the goal list. Furthermore, there are numerous improvements to error recovery (including
allGoals-type logic for pre-tactics) and the visible tactic states when there are errors. AddsTactic.throwOrLogErrorAt/Tactic.throwOrLogErrorfor throwing or logging errors depending on the recovery state. -
#9571 restores the feature where in
induction/casesforNat, thezeroandsucclabels are hoverable. This was added in #1660, but broken in #3629 and #3655 when custom eliminators were added. In general, if a custom eliminatorT.elimfor an inductive typeThas an alternativefoo, andT.foois a constant, then thefoolabel will haveT.foohover information. -
#9574 adds the option
abstractProofto control whethergrindautomatically creates an auxiliary theorem for the generated proof or not. -
#9575 optimizes the proof terms generated by
grind ring. For example, before this PR, the kernel took 2.22 seconds (on a M4 Max) to type-check the proof in the benchmarkgrind_ring_5.lean; it now takes only 0.63 seconds. -
#9578 fixes an issue in
grind's disequality proof construction. The issue occurs when an equality is merged with theFalseequivalence class, but it is not the root of its congruence class, and its congruence root has not yet been merged into theFalseequivalence class yet. -
#9579 ensures
iteandditeare to selected as E-matching patterns. They are bad patterns because the then/else branches are only internalized aftergrinddecided whether the condition isTrue/False. -
#9592 updates the styling and wording of error messages produced in inductive type declarations and anonymous constructor notation, including hints for inferable constructor visibility updates.
-
#9595 improves the error message displayed when writing an invalid projection on a free variable of function type.
-
#9606 adds notes to the deprecation warning when the replacement constant has a different type, visibility, and/or namespace.
-
#9625 improves trace messages around wf_preprocess.
-
#9628 introduces a
mutual_inductvariant of the generated (co)induction proof principle for mutually defined (co)inductive predicates. Unlike the standard (co)induction principle (which projects conclusions separately for each predicate),mutual_inductproduces a conjunction of all conclusions. -
#9633 updates various error messages produced by or associated with built-in tactics and adapts their formatting to current conventions.
-
#9634 modifies dot identifier notation so that
(.a : T)resolvesT.awith respect to the root namespace, like for generalized field notation. This lets the notation refer to private names, follow aliases, and also use open namespaces. The LSP completions are improved to follow how dot ident notation is resolved, but it doesn't yet take into account aliases or open namespaces. -
#9637 improves the readability of the "maximum universe level offset exceeded" error message.
-
#9646 uses a more simple approach to proving the unfolding theorem for a function defined by well-founded recursion. Instead of looping a bunch of tactics, it uses simp in single-pass mode to (try to) exactly undo the changes done in
WF.Fix, using a dedicated theorem that pushes the extra argument in for each matcher (orcasesOn). -
#9649 fixes an issue where a macro unfolding to multiple commands would not be accepted inside
mutual -
#9653 adds error explanations for two common errors caused by large elimination from
Prop. To support this functionality, "nested" named errors thrown by sub-tactics are now able to display their error code and explanation. -
#9666 addresses an outstanding feature in the module system to automatically mark
let recandwherehelper declarations as private unless they are defined in a public context such as under@[expose]. -
#9670 add constructors
.intCast kand.natCast ktoCommRing.Expr. We need them because terms such asNat.cast (R := α) 1and(1 : α)are not definitionally equal. This is pervaise in Mathlib for the numerals0and1. -
#9671 fixes support for
SMul.smulingrind ring.SMul.smulapplications are now normalized. Example:example (x : BitVec 2) : x - 2 • x + x = 0 := by grind
-
#9675 adds support for
Fin.valingrind cutsat. Examples:example (a b : Fin 2) (n : Nat) : n = 1 → ↑(a + b) ≠ n → a ≠ 0 → b = 0 → False := by grind
-
#9676 adds normalizers for nonstandard arithmetic instances. The types
NatandInthave built-in support ingrind, which uses the standard instances for these types and assumes they are the ones in use. However, users may define their own alternative instances that are definitionally equal to the standard ones. normalizes such instances using simprocs. This situation actually occurs in Mathlib. Example:class Distrib (R : Type _) extends Mul R where
-
#9679 produces a warning for redundant
grindarguments. -
#9682 fixes a regression introduced by an optimization in the
unfoldReduciblestep used by thegrindnormalizer. It also ensures that projection functions are not reduced, as they are folded in a later step. -
#9686 applies
clearto implementation detail local declarations during thegrindpreprocessing steps. -
#9699 adds propagation rules for functions that take singleton types. This feature is useful for discharging verification conditions produced by
mvcgen. For example:example (h : (fun (_ : Unit) => x + 1) = (fun _ => 1 + y)) : x = y := by grind
-
#9700 fixes assertion violations when
checkInvariantsis enabled ingrind -
#9701 switches to a non-verloading local
Std.Do.Triplenotation in SpecLemmas.lean to work around a stage2 build failure. -
#9702 fixes an issue in the
matchelaborator where pattern variables like__xwould not have the kindimplDetailin the local context. NowkindOfBinderNameisLocalDeclKind.ofBinderName. -
#9704 optimizes the proof terms produced by
grind cutsat. Additional performance improvements will be merged later. -
#9706 combines
Poly.combine_kandPoly.mul_ksteps used in thegrind cutsatproof terms. -
#9710 improves some of the proof terms produced by
grind ringandgrind cutsat. -
#9714 adds a version of
CommRing.Expr.toPolyoptimized for kernel reduction. We use this function not only to implementgrind ring, but also to interface the ring module withgrind cutsat. -
#9716 moves the validation of cross-package
import allto Lake and the syntax validation of import keywords (public,meta, andall) to the two import parsers. -
#9728 fixes #9724
-
#9735 extends the propagation rule implemented in #9699 to constant functions.
-
#9736 implements the option
mvcgen +jpto employ a slightly lossy VC encoding for join points that prevents exponential VC blowup incurred by naïve splitting on control flow. -
#9754 make
mleaveapplyat *and improve its simp set in order to discharge some more trivialities (#9581). -
#9755 implements a
mrevert ∀ntactic that "eta-reduces" the stateful goal and is adjoint tomintro ∀x1 ... ∀xn. -
#9767 fixes equality congruence proof terms contructed by
grind. -
#9772 fixes a bug in the projection over constructor propagator used in
grind. It may construct type incorrect terms when a equivalence class contains heterogeneous equalities. -
#9776 combines the simplification and unfold-reducible-constants steps in
grindto ensure that no potential normalization steps are missed. -
#9780 extends the test suite for
grindworking category theory, to help debug outstanding problems in Mathlib. -
#9781 ensures that
mvcgenis hygienic. The goals it generates should now introduce all locals inaccessibly. -
#9785 splits out an implementation detail of MVarId.getMVarDependencies into a top-level function. Aesop was relying on the function defined in the where clause, which is no longer possible after #9759.
-
#9798 introduces
Lean.realizeValue, a new metaprogramming API for parallelism-aware caching ofMetaMcomputations -
#9800 improves the delta deriving handler, giving it the ability to process definitions with binders, as well as the ability to recursively unfold definitions. Furthermore, delta deriving now tries all explicit non-out-param arguments to a class, and it can handle "mixin" instance arguments. The
derivingsyntax has been changed to accept general terms, which makes it possible to derive specific instances with for examplederiving OfNat _ 1orderiving Module R. The class is allowed to be a pi type, to add additional hypotheses; here is a Mathlib example:def Sym (α : Type*) (n : ℕ) := { s : Multiset α // Multiset.card s = n } deriving [DecidableEq α] → DecidableEq _This underscore stands for where
Sym α nmay be inserted, which is necessary when→is used. Thederiving instancecommand can refer to scoped variables when delta deriving as well. Breaking change: the derived instance's name uses theinstancecommand's name generator, and the new instance is added to the current namespace. -
#9804 allows trailing comma in the argument list of
simp?,dsimp?,simpa, etc... Previously, it was only allowed in the non?variants ofsimp,dsimp,simp_all. -
#9807 adds
Std.List.Zipper.prefto the simp set ofmleave. -
#9809 adds a script for analyzing
grindE-matching annotations. The script is useful for detecting matching loops. We plan to add user-facing commands for running the script in the future. -
#9813 fixes an unexpected bound variable panic in
unfoldReducibleused ingrind. -
#9814 skips the
normalizeLevelspreprocessing step ingrindwhen it is not needed. -
#9818 fixes a bug where the
DecidableEqderiving handler did not take universe levels into account for enumerations (inductive types whose constructors all have no fields). Closes #9541. -
#9819 makes the
unsafe tterm create an auxiliary opaque declaration, rather than an auxiliary definition with opaque reducibility hints. -
#9831 adds a delaborator for
Std.Rangenotation. -
#9832 adds simp lemmas
SPred.entails_<n>to replaceSPred.entails_conswhich was disfunctional as a simp lemma due to #8074. -
#9833 works around a DefEq bug in
mspecinvolving delayed assignments. -
#9834 fixes a bug in
mvcgentriggered by excess state arguments to thewpapplication, a situation which arises when working withStateTprimitives. -
#9841 migrates the ⌜p⌝ notation for embedding pure p : Prop into SPred σs to expand into a simple, first-order expression SPred.pure p that can be supported by e-matching in grind.
-
#9843 makes
mvcgenproduce deterministic case labels for the generated VCs. Invariants will be namedinv<n>and every other VC will be namedvc<n>.*, where the*part serves as a loose indication of provenance. -
#9852 removes the
inShareCommonquick filter used ingrindpreprocessing steps.shareCommonis no longer used only for fully preprocessed terms. -
#9853 adds
NatandIntnumeral normalizers ingrind. -
#9857 ensures
grindcan E-match patterns containing universe polymorphic ground sub-patterns. For example, givenset_option pp.universes true in attribute [grind?] Id.run_pure
the pattern
Id.run_pure.{u_1}: [@Id.run.{u_1} #1 (@pure.{u_1, u_1} `[Id.{u_1}] `[Applicative.toPure.{u_1, u_1}] _ #0)]contains two nested universe polymorphic ground patterns
-
Id.{u_1} -
Applicative.toPure.{u_1, u_1}
-
-
#9860 fixes E-matching theorem activation in
grind. -
#9865 adds improved support for proof-by-reflection to the kernel type checker. It addresses the performance issue exposed by #9854. With this PR, whenever the kernel type-checks an argument of the form
eagerReduce _, it enters "eager-reduction" mode. In this mode, the kernel is more eager to reduce terms. The neweagerReduce _hint is often used to wrapEq.refl true. The new hint should not negatively impact any existing Lean package. -
#9867 fixes a nondeterministic behavior in
grind ring. -
#9880 ensures a local forall is activated at most once per pattern in
grind. -
#9883 refines the warning message for redundant
grindarguments. It is not based on the actual inferred pattern instead provided kind. -
#9885 is initially motivated by noticing
Lean.Grind.Preorder.toLEappearing in long Mathlib typeclass searches; this change will prevent these searches. These changes are also helpful preparation for potentially dropping the customLean.Grind.*typeclasses, and unifying with the new typeclasses introduced in #9729.
Library
-
#7450 implements
Nat.dfold, a dependent analogue ofNat.fold. -
#9096 removes some unnecessary
Decidable*instance arguments by using lemmas in theClassicalnamespace instead of theDecidablenamespace. -
#9121 allows
grindto case on the universe variants ofProd. -
#9129 fixes simp lemmas about boolean equalities to say
(!x) = yinstead of(!decide (x = y)) = true -
#9135 allows the result type of
forIn,foldMandfoldon pure iterators (Iter) to be in a different universe than the iterators. -
#9142 changes
Fin.reverseInductionfrom using well-founded recursion to usinglet rec, which makes it have better definitional equality. Co-authored by @digama0. See the test below:namespace Fin
-
#9145 fixes two typos.
-
#9176 makes
mvcgensplit ifs rather than applying specifications. Doing so fixes a bug reported by Rish. -
#9194 makes the logic and tactics of
Std.Douniverse polymorphic, at the cost of a few definitional properties arising from the switch fromProptoULift Propin the base caseSPred []. -
#9249 adds theorem
BitVec.clzAuxRec_eq_clzAuxRec_of_getLsbD_falseas a more general statement thanBitVec.clzAuxRec_eq_clzAuxRec_of_le, replacing the latter in the bitblaster too. -
#9260 removes uses of
Lean.RBMapin Lean itself. -
#9263 fixes
toISO8601Stringto produce a string that conforms to the ISO 8601 format specification. The previous implementation separated the minutes and seconds fragments with a.instead of a:and included timezone offsets without the hour and minute fragments separated by a:. -
#9285 removes the unnecessary requirement of
BEq αforArray.any_push,Array.any_push',Array.all_push,Array.all_push'as well asVector.any_pushandVector.all_push. -
#9301 adds a
simpand agrindannotation onZipper-related theorems to improve reasoning aboutStd.Doinvariants. -
#9391 replaces the proof of the simplification lemma
Nat.zero_modwithrflsince it is, by design, a definitional equality. This solves an issue whereby the lemma could not be used by the simplifier when in 'dsimp' mode. -
#9441 fixes the behavior of
String.prev, aligning the runtime implementation with the reference implementation. In particular, the following statements hold now:-
(s.prev p).byteIdxis at leastp.byteIdx - 4and at mostp.byteIdx - 1 -
s.prev 0 = 0 -
s.previs monotone
-
-
#9449 fix the behavior of
String.nexton the scalar boundary (2 ^ 63 - 1on 64-bit platforms). -
#9451 adds support in the
mintrotactic for introducinglet/havebinders in stateful targets, akin tointro. This is useful when specifications introduce such let bindings. -
#9454 introduces tactic
mleavethat leaves theSPredproof mode by eta expanding through its abstractions and applying some mild simplifications. This is useful to apply automation such asgrindafterwards. -
#9504 adds a few more
*.by_wp"adequacy theorems" that allows to prove facts about programs inReaderMandExceptMusing theStd.Doframework. -
#9528 adds
List.zipWithMandArray.zipWithM. -
#9529 upstreams some helper instances for
NameSetfrom Batteries. -
#9538 adds two lemmas related to
Iter.toArray. -
#9577 adds lemmas about
UIntX.toBitVecandUIntX.ofBitVecand^. -
#9586 adds componentwise algebraic operations on
Vector α n, and relevant instances. -
#9594 optimizes
Lean.Name.toString, giving a 10% instruction benefit. -
#9609 adds
@[grind =]toProd.lex_def. Note thatomegahas special handling forProd.Lex, and this is needed forgrind's cutsat module to achieve parity. -
#9616 introduces checks to make sure that the IO functions produce errors when inputs contain NUL bytes (instead of ignoring everything after the first NUL byte).
-
#9620 adds the separate directions of
List.pairwise_iff_forall_sublistas named lemmas. -
#9621 renames
XortoXorOp, to matchAndOp, etc. -
#9622 adds a missing lemma about
List.sum, and a grind annotation. -
#9701 switches to a non-verloading local
Std.Do.Triplenotation in SpecLemmas.lean to work around a stage2 build failure. -
#9721 tags more
SIntandUIntlemmas withint_toBitVecsobv_decidecan handle casts between them and negation. -
#9729 introduces a canonical way to endow a type with an order structure. The basic operations (
LE,LT,Min,Max, and in later PRsBEq,Ord, ...) and any higher-level property (a preorder, a partial order, a linear order etc.) are then put in relation toLEas necessary. The PR providesIsLinearOrderinstances for many core types and updates the signatures of some lemmas. -
#9732 re-implements
IO.waitAnyusing Lean instead of C++. This is to reduce the size and complexity oftask_managerin order to ease future refactorings. -
#9736 implements the option
mvcgen +jpto employ a slightly lossy VC encoding for join points that prevents exponential VC blowup incurred by naïve splitting on control flow. -
#9739 removes the
instanceattribute fromlexOrdthat was accidentally applied inStd.Classes.Ord.Basic. -
#9757 adds
grindannotations for keyStd.Do.SPredlemmas. -
#9782 corrects the
Inhabitedinstance ofStdGento use a valid initial state for the pseudorandom number generator. Previously, thedefaultgenerator had the property thatProd.snd (stdNext default) = default, so it would produce only constant sequences. -
#9787 adds a simp lemma
PostCond.const_apply. -
#9792 adds
@[expose]to two definitions withwhereclauses that Batteries proves theorems about. -
#9799 fixes the #9410 issue.
-
#9805 improves the API for invariants and postconditions and as such introduces a few breaking changes to the existing pre-release API around
Std.Do. It also adds Markus Himmel'spairsSumToZeroexample as a test case. -
#9832 adds simp lemmas
SPred.entails_<n>to replaceSPred.entails_conswhich was disfunctional as a simp lemma due to #8074. -
#9841 migrates the ⌜p⌝ notation for embedding pure p : Prop into SPred σs to expand into a simple, first-order expression SPred.pure p that can be supported by e-matching in grind.
-
#9848 adds
@[spec]lemmas forforInandforIn'atStd.PRange. -
#9850 add a delaborator for
Std.PRangenotation.
Compiler
-
#8691 ensures that the state is reverted when compilation using the new compiler fails. This is especially important for noncomputable sections where the compiler might generate half-compiled functions which may then be erroneously used while compiling other functions.
-
#9134 changes ToIR to call
lowerEnumToScalarType?withConstructorVal.inductrather than the name of the constructor itself. This was an oversight in some refactoring of code in the new compiler before landing it. It should not affect runtime of compiled code (due to the extra tagging/untagging being optimized by LLVM), but it does make IR for the interpreter slightly more efficient. -
#9144 adds support for representing more inductive as enums, summarized up as extending support to those that fail to be enums because of parameters or irrelevant fields. While this is nice to have, it is actually motivated by correctness of a future desired optimization. The existing type representation is unsound if we implement
object/tobjectdistinction between values guaranteed to be an object pointer and those that may also be a tagged scalar. In particular, types like the ones added in this PR's tests would have all of their constructors encoded via tagged values, but under the natural extension of the existing rules of type representation they would be consideredobjectrather thantobject. -
#9154 tightens the IR typing rules around applications of closures. When re-reading some code, I realized that the code in
mkPartialApphas a clear typo—.objectandtypeshould be swapped. However, it doesn't matter, because later IR passes smooth out the mismatch here. It makes more sense to be strict up-front and require applications of closures to always return an.object. -
#9159 enforces the non-inlining of _override impls in the base phase of LCNF compilation. The current situation allows for constructor/cases mismatches to be exposed to the simplifier, which triggers an assertion failure. The reason this didn't show up sooner for Expr is that Expr has a custom extern implementation of its computed field getter.
-
#9177 makes the
pullInstancespass avoid pulling any instance expressions containing erased propositions, because we don't correctly represent the dependencies that remain after erasure. -
#9198 changes the compiler's specialization analysis to consider higher-order params that are rebundled in a way that only changes their
Proparguments to be fixed. This means that they get specialized with a mere@[specialize], rather than the compiler having to opt-in to more aggressive parameter-specific specialization. -
#9207 makes the offending declaration clickable in the error message produced when something should be marked
noncomputable. -
#9209 changes the
getLiteralhelper function ofelimDeadBranchesto correctly handle inductives with constructors. This function is not used as often as it could be, which makes this issue rare to hit outside of targeted test cases. -
#9218 makes the LCNF
elimDeadBranchespass handle unsafe decls a bit more carefully. Now the result of an unsafe decl will only become ⊤ if there is value flow from a recursive call. -
#9221 removes code that has the false assumption that LCNF local vars can occur in types. There are other comments in
ElimDead.leanasserting that this is not possible, so this must have been a change early in the development of the new compiler. -
#9224 changes the
toMonopass to consider the type of an application and erase all arguments corresponding to erased params. This enables a lightweight form of relevance analysis by changing the mono type of a decl. I would have liked to unify this with the behavior for constructors, but my attempt to give constructors the same behavior in #9222 (which was in preparation for this PR) had a minor performance regression that is really incidental to the change. Still, I decided to hold off on it for the time being. In the future, we can hopefully extend this to constructors, extern decls, etc. -
#9266 adds support for
.mdatain LCNF mono types (and then drops it at the IR type level instead). This better matches the behavior of extern decls in the C++ code of the old compiler, which is still being used to create extern decls at the moment and will soon be replaced. -
#9268 moves the implementation of
lean_add_extern/addExternfrom C++ into Lean. I believe is the last C++ helper function from the library/compiler directory being relied upon by the new compiler. I put it into its own file and duplicated some code because this function needs to execute in CoreM, whereas the other IR functions live in their own monad stack. After the C++ compiler is removed, we can move the IR functions into CoreM. -
#9275 removes the old compiler written in C++.
-
#9279 fixes the
compiler.extract_closedoption after migrating it to Lean (and adds a test so it would be caught in the future). -
#9310 fixes IR constructor argument lowering to correctly handle an irrelevant argument being passed for a relevant parameter in all cases. This happened because constructor argument lowering (incompletely) reimplemented general LCNF-to-IR argument lowering, and the fix is to just adopt the generic helper functions. This is probably due to an incomplete refactoring when the new compiler was still on a branch.
-
#9336 changes the implementation of
trace.Compiler.resultto use the decls as they are provided rather than looking them up in the LCNF mono environment extension, which was seemingly done to save the trouble of re-normalizing fvar IDs before printing the decl. This means that the._closeddecls created by theextractClosedpass will now be included in the output, which was definitely confusing before if you didn't know what was happening. -
#9344 correctly populates the
xTypefield of theIR.FnBody.caseconstructor. It turns out that there is no obvious consequence for this being incorrect, because it is conservatively recomputed by theBoxingpass. -
#9393 fixes an unsafe trick where a sentinel for a hash table of Exprs (keyed by pointer) is created by constructing a value whose runtime representation can never be a valid Expr. The value chosen for this purpose was Unit.unit, which violates the inference that Expr has no scalar constructors. Instead, we change this to a freshly allocated Unit × Unit value.
-
#9411 adds support for compilation of
casesOnfor subsingletons. We rely on the elaborator's type checking to restrict this to inductives inPropthat can actually eliminate intoType n. This does not yet cover other recursors of these types (or of inductives not inPropfor that matter). -
#9703 changes the LCNF
elimDeadBranchespass so that it considers all non-Natliteral types to be⊤. It turns out that fixing this to correctly handle all of these types with the current abstract value representation is surprisingly nontrivial, and it's better to just land the fix first. -
#9720 removes an error which implicitly assumes that the sort of type dependency between erased types present in the test being added can not occur. It would be difficult to refine the error using only the information present in LCNF types, and it is of very little ongoing value (I don't recall it ever finding an actual problem), so it makes more sense to delete it.
-
#9827 changes the lowering of
Quot.lcInv(the compiler-internal form ofQuot.lift) intoMonoto support overapplication. -
#9847 adds a check for reursive decls in this bespoke inlining path, which fixes a regression from the old compiler.
-
#9864 adds new variants of
Array.getInternalandArray.get!Internalthat return their argument borrowed, i.e. without a reference count increment. These are intended for use by the compiler in cases where it can determine that the array will continue to hold a valid reference to the element for the returned value's lifetime.
Pretty Printing
-
#8391 adds an unexpander for
Vector.mkthat unexpandsVector.mk #[...] _to#v[...].-- previously: #check #v[1, 2, 3] -- { toArray := #[1, 2, 3], size_toArray := ⋯ } : Vector Nat 3 -- now: #check #v[1, 2, 3] -- #v[1, 2, 3] : Vector Nat 3 -
#9475 fixes the way some syntaxes are pretty printed due to missing whitespace advice.
-
#9494 fixes an issue that caused some error messages to attempt to display hovers for nonexistent identifiers.
-
#9555 allows hints in message data to specify custom preview spans that extend beyond the edit region specified by the code action.
-
#9778 modifies the pretty printing of anonymous metavariables to use the index rather than the internal name. This leads to smaller numerical suffixes in
?m.123since the indices are numbered within a given metavariable context rather than across an entire file, hence each command gets its own numbering. This does not yet affect pretty printing of universe level metavariables.
Documentation
Server
-
#9040 improves the 'Go to Definition' UX, specifically:
-
Using 'Go to Definition' on a type class projection will now extract the specific instances that were involved and provide them as locations to jump to. For example, using 'Go to Definition' on the
toStringoftoString 0will yield results forToString.toStringandToString Nat. -
Using 'Go to Definition' on a macro that produces syntax with type class projections will now also extract the specific instances that were involved and provide them as locations to jump to. For example, using 'Go to Definition' on the
+of1 + 1will yield results forHAdd.hAdd,HAdd α α αandAdd Nat. -
Using 'Go to Declaration' will now provide all the results of 'Go to Definition' in addition to the elaborator and the parser that were involved. For example, using 'Go to Declaration' on the
+of1 + 1will yield results forHAdd.hAdd,HAdd α α α,Add Nat,macro_rules | `($x + $y) => ...andinfixl:65 " + " => HAdd.hAdd. -
Using 'Go to Type Definition' on a value with a type that contains multiple constants will now provide 'Go to Definition' results for each constant. For example, using 'Go to Type Definition' on
xforx : Array Natwill yield results forArrayandNat.
-
-
#9163 disables the use of the header produced by
lake setup-filein the server for now. It will be re-enabled once Lake takes into account the header given by the server when processing workspace modules. Without that,setup-fileheader can produce odd behavior when the file on disk and in an editor disagree on whether the file participates in the module system. -
#9563 performs some micro optimizations on fuzzy matching for a
~20%instructions win. -
#9784 ensures the editor progress bar better reflects the actual progress of parallel elaboration.
Lake
-
#9053 updates Lake to resolve the
.oleanfiles for transitive imports for Lean through themodulesfield oflean --setup. This enables means the Lean can now directly use the.oleanfiles from the Lake cache without needed to locate them at a specific hierarchical path. -
#9101 fixes a bug introduce by #9081 where the source file was dropped from the module input trace and some entries were dropped from the module job log.
-
#9162 changes the key Lake uses for the
,irartifact in the content hash data structure tor, maintaining the convention of single character key names. -
#9165 fixes two issues with Lake's process of creating static archives.
-
#9332 changes the dependency cloning mechanism in lake so the log message that lake is cloning a dependency occurs before it is finished doing so (and instead before it starts). This has been a huge source of confusion for users that don't understand why lake seems to be just stuck for no reason when setting up a new project, the output now is:
λ lake +lean4 new math math info: downloading mathlib `lean-toolchain` file info: math: no previous manifest, creating one from scratch info: leanprover-community/mathlib: cloning https://github.com/leanprover-community/mathlib4 <hang> info: leanprover-community/mathlib: checking out revision 'cd11c28c6a0d514a41dd7be9a862a9c8815f8599'
-
#9434 changes the Lake local cache infrastructure to restore executables and shared and static libraries from the cache. This means they keep their expected names, which some use cases still rely on.
-
#9435 adds the
libPrefixOnWindowspackage and library configuration option. When enabled, Lake will prefix static and shared libraries withlibon Windows (i.e., the same way it does on Unix). -
#9436 adds the number of jobs run to the final message Lake produces on a successfully run of
lake build. -
#9478 adds proper Lake support for
meta import. Module IR is now tracked in traces and in the pre-resolved modules Lake passes tolean --setup. -
#9525 fixes Lake's handling of a module system
import all. Previously, Lake treatedimport allthe same a non-moduleimport, importing all private data in the transitive import tree. Lake now distinguishes the two, withimport all Mjust importing the private data ofM. The direct private imports ofMare followed, but they are not promoted. -
#9559 changes
lake setup-fileto use the server-provided header for workspace modules. -
#9604 restricts Lake's production of thin archives to only the Windows core build (i.e.,
bootstrap = true). The unbundledarusually used for core builds on macOS does not support--thin, so we avoid using it unless necessary. -
#9677 adds build times to each build step of the build monitor (under
-vor in CI) and delays exiting on a--no-builduntil after the build monitor finishes. Thus, a--no-buildfailure will now report which targets blocked Lake by needing a rebuild. -
#9697 fixes the handling in
lake leanandlake setup-fileof a library source file with multiple dots (e.g.,src/Foo.Bar.lean). -
#9698 adjusts the formatting type classes for
lake queryto no longer require both a text and JSON form and instead work with any combination of the two. The classes have also been renamed. In addition, the query formatting of a text module header has been improved to only produce valid headers.
Other
-
#9106 fixes
undefined symbol: lean::mpz::divexact(lean::mpz const&, lean::mpz const&)when building withoutLEAN_USE_GMP -
#9114 further improves release automation, automatically incorporating material from
nightly-testingandbump/v4.X.0branches in the bump PRs to downstream repositories. -
#9659 fixes compatibility of the
trace.profiler.outputoption with newer versions of Firefox Profiler