These release notes describe a release candidate, not the final release. They may be incomplete and are subject to change.
Lean 4.33.0-rc1 (2026-07-15)
For this release, 194 changes landed. In addition to the 53 feature additions, and 41 fixes listed below, there were 12 refactoring changes, 11 documentation improvements, 21 performance improvements, 6 improvements to the test suite, and 50 other changes.
Language
-
#14352 provides the experimental
postprocess_traces tracePostprocessor in cmdcommand, which is useful for working with large trees of trace nodes. It runs the commandcmdand then transforms the traces using a functiontracePostprocessor. The transformation can affect which nodes are expanded or collaped by default, it can change messages of the trace nodes, and it can add or delete nodes. Example:module meta import Lean.PostprocessTraces -- Expand all ancestors of `synthInstance` trace nodes -- for better discoverability in large trace trees postprocess_traces exposeSubtrees (ofClass `Meta.synthInstance) in set_option trace.Meta.isDefEq true in set_option trace.Meta.synthInstance true in def x ...
-
#14375 adds proper borrow annotations to
Syntax.structEq. They are needed because it is so early in bootstrapping that it routes throughSubstring's bootstrapping wrappers without borrow annotations. They are relevant becauseSyntax.structEqends up getting called transitively fromalphaEq. -
#14196 improves on the warnings and errors regarding reducibility attributes. Partially addresses #13351.
-
#14361 optimizes
applyAbstractResult?by attempting to skip thecheckinvocation used to propagate universe constraints. The optimization is very simple: it checks whether the result contains any metavariables that may be assigned. -
#14333 makes the
@[deprecated]attribute error when deprecating a declaration in favor of itself. -
#14325 adds a linter which warns on
openstatements which do not in fact open all namespaces which end in the given name. -
#14335 makes
partial_fixpointreport a helpful monotonicity error instead of a confusingUnknown constanterror when a non-monadic definition uses a nested recursive call (e.g.f (f x)), which requires the function to be tail recursive. -
#14330 makes
tryResolveassign the goal metavariable directly after successfully unifying the goal type with the candidate instance type, instead of re-checking the types withisDefEq. The recheck is redundant for metavariable-free goals and can be expensive. -
#14259 adds a hint to a
unusedVariableslinter, suggesting to rename the unreferenced name with an underscore. -
#14153 adds
Insertinstances forNameMapandNameSet. -
#13956 makes the kernel's
(kernel) deep recursion detectederror deterministic by bounding kernel type checking with the existingmaxRecDepthoption instead of the physical stack size. The limit previously depended on the native stack, so it varied across platforms, builds, and optimization levels and could not be reproduced reliably; it is now a function ofmaxRecDepthalone and is raised the usual way withset_option maxRecDepth <num>. -
#14297 makes a bare
returninside amatch (dependent := true)branch of adoblock target the dependently-refined branch type, so a branch like| 0 => return 0type-checks against the refineddo-block result type without wrapping it in a nested(do β¦). -
#13895 enables the
backward.isDefEq.respectTransparency.typesoption by default. When assigning a metavariable at reducible, instances or implicit transparency, this means that the metavariable's and its assigned value's types are compared at implicit, previously default, transparency. It also makes many existing declarations implicit-reducible. This change increases users' control over what is being unfolded, improving scalability for large projects. -
#14249 extends
dupNamespacelinter to allow users to opt-in vialinter.extra.dupNamespace.consecutiveOnlyoption to check non-consecutive repeated usages of namespace components. By default, only consecutive ones are checked. Opting in for non-consecutive checks matches the behaviour introduced in mathlib4#39793. -
#14247 fixes an error ("Couldn't interpret binder") when a docstring is attached to a
coinductivepredicate anddoc.versois enabled. -
#14234 fixes autocompletion (and other InfoTree-driven consumers such as the interactive term goal and hover popups) to see the augmented
openDeclsandoptionswhen the cursor is under a term-levelopen ... in <term>orset_option ... in <term>scope. Previously both elaborators only updated the runtimeCore.ContextviawithTheReader/withOptions, but did not push a correspondingPartialContextInfo.commandCtxnode into the InfoTree; consumers therefore saw the outer command'sopenDecls/optionsand, for example, offered names fully-qualified even under a matchingopen, or rendered pretty-printed goals ignoring a localset_option pp.fullNames true. -
#14214 reverts leanprover/lean4#14193 . The benchmark issue that it was a reaction to was almost certainly not caused by it, but was instead noise; the actual gains were modest compared to the downside of a more complex mental model for users.
-
#14200 causes docstrings in macros to follow the value of the
doc.versooption at the the macro's definition site, rather than its use site. Before, the use-site option was used, making it impossible to use macros in contexts where the option's value disagreed because the parsed format was incorrect. Now, the parsed format in the syntax is used regardless of the option's local setting. -
#14198 fixes a bug where references to parameters by names failed for unbracketed binders, in the presence of
_parameters, and in macro-generated declarations. -
#14191 fixes an issue where escaped content at the start of a line in a valid block-opening positon in Verso content was skipped as if it were whitespace.
-
#14193 restricts the options propagated to parsers to those that start with
doc.verso, to improve performance over #14189. -
#14189 propagates the values of options from set_option ... in ... forms used in commands, terms, and tactics into the parsing of the body. This means that Verso syntax can be more conveniently enabled or disabled, and brings
set_option ... in ...semantically in line withopen ... in .... -
#14115 adds support for extensible Markdown rendering of Verso docstrings.
-
#14181 lets
matchuseFloatandFloat32literals as patterns, just likeString,UInt64, and other literal types. The compiler compares the scrutinee against each literal using the type'sDecidableEqinstance (bit-pattern equality), so e.g.0.0and-0.0are distinct patterns. Negative literals such as-1.5are supported. -
#14114 changes the Hoare-triple notation so
;introduces the exceptional postcondition as a singleEPredterm rather than a list of exception cases wrapped inepostβ¨β¦β©. This lets the notation express anepostvariable or anyEPred, and makesepostβ¨β¦β©an ordinary explicit constructor written in that slot. -
#13637 splits
TransparencyMode.instancesandReducibilityStatus.implicitReducibleinto two transparency levels so that@[implicit_reducible]annotations no longer have the side effects@[instance_reducible]has, such as allowing type class search to see through the marked declarations. -
#14120 fixes language server-oriented API such as
findDocString?that sources its information from.olean.serverunder the module system to also work on the cmdline if the module in question is imported withall. -
#14112 adds the
wait_for_expected_type%term elaborator, which elaborates its argument against the expected type but postpones while that type is an unassigned metavariable. This lets a notation defer an assertion until anoutParamis resolved by instance synthesis, so a bare lambda checks against the folded carrier instead of unfolding it into a pointwise function lattice.
Library
-
#14303 removes helper definitions used by the builtin simprocs for basic types from the respective namespaces.
-
#14302 moves three public lemmas about
ExceptTout ofStd.Internal.Do.WP.Lemmas(an internal module) toInit.Control.Lawful.Instances, where the rest of theExceptTlemmas live. -
#14293 moves the public declaration
Function.Injective.leftInverseout ofInit.Grindand intoInit.Data.Function. -
#14255 renames
Int.LineartoInt.Internal.Linearto make it more clear that these are internal implementation details ofomega/grind/simp +arithand should not be relied on directly by users. -
#14265 moves various declarations that were polluting public namespaces into internal namespaces (like
Lean). -
#14269 makes Windows transition times use ceil when converting seconds, which avoids dropping fractional seconds and causing off-by-one behavior.
-
#14231 marks
Array.back,Array.back!, andArray.back?as@[expose], so that in a downstream module their bodies are available for definitional reduction. Previouslydecidecould not evaluate goals such as#[1, 2, 3].back? = some 3from another module, even though thegetElem?/sizeaccessors these functions are defined in terms of are already exposed. -
#14267 makes
Fin.foldlreduce in the kernel by marking its innerloopsemireducible(well-founded definitions areirreducibleby default) and exposingfoldl, so the kernel's special support for well-founded recursion onNatapplies. PreviouslyFin.foldlgot stuck underdecide/#reduce/Decidable, unlike the already-reducingFin.foldr:example : Fin.foldl 8 (fun a i => a + i.val) 0 = 28 := by decide -- now succeeds
-
#13804 adds the parsing of Posix TZ String (generating a
RecurringRuletype) in TzIf V2 and V3 footer so lean can generate timezone transitions in case the timestamp is not covered by the transitions array inZoneRules. -
#14263 renames
IO.AsyncListtoLean.AsyncListto avoid polluting the publicIOnamespace. -
#14260 moves some declarations in
Lean.Data.Lsp.Communicationthat were polluting the globalIO.FS.Streamnamespace into an internal namespace. -
#14258 moves the declarations in
Lean.Data.Lsp.Utf16fromChartoChar.Internaland fromStringtoString.Internal, so that theStringnamespace is not polluted in this implementation module. -
#14256 renames the
LLVMnamespace toLean.LLVMin order to reduce pollution of the global namespace. -
#14252 speeds up
Selectable.one,Selectable.combine, andSelectable.tryOneby using a cheap randomness source as opposed to calling intogetRandomBytesevery time. -
#14244 replaces "can seen" with "can be seen" in the documentation of
Quotand rewraps the paragraph to fit 100 columns without splitting short snippets. -
#14212 adds
List.Nodup.length_le_of_subset: a duplicate-free list that is a subset of another list is no longer than that list. This is currently only available in Batteries (via theSubpermAPI); here it is proved directly by induction. -
#14211 adds
List.perm_ext_iff_of_nodup: two duplicate-free lists are permutations of each other if and only if they have the same elements. This is currently only available in Batteries (where it is proved viaSubperm); here it is proved directly fromperm_iff_count. -
#14210 adds the round-trip lemmas between
List.idxOfand indexing:List.getElem_idxOf(xs[xs.idxOf x] = xwhenxoccurs inxs) andList.Nodup.idxOf_getElem(idxOf xs[i] xs = ifor a duplicate-freexs). These are currently only available in Batteries. -
#14216 marks
Nat.ne_of_gtasprotectedso that it must be referred to by its fully qualified name, consistent with the surroundingNatorder lemmas. In-namespace references are updated to the qualified name accordingly. -
#14209 adds
List.pairwise_lt_finRange,List.pairwise_le_finRange, andList.nodup_finRange, stating thatList.finRange nis strictly increasing, increasing, and free of duplicates. These are basic facts aboutfinRangecurrently only available in Batteries. -
#14177 reduces the aggressiveness of e-matching for
List.countandArray.count. Previously, any invocation of count would directly trigger theory about filter. However, given thatcounthas its own set ofgrindannotations, we believe thatcountshould only start connecting withfilter, when an invocation offilteris already available in the e-graph. This way we do not unnecessarily triggerfiltertheory fromcount. -
#14194 reduces the aggressiveness of e-matching for
eraseIdxby not automatically translating intodrop/takeanymore at every opportunity. -
#14192 reduces the aggressiveness of e-matching annotations for bounding the result of
countoperations above by the size of their container. They now only get triggered when the size and count operations are both already in the e-graph. Similarly to how find's annotations work. -
#14190 adds two small, independent pieces of
Lean.Order.CompleteLatticeinfrastructure used by theStd.Internal.Doverification framework. -
#14182 stops automatically connected
findIdxtofindIdx?through e-matching wheneverfindIdxis available and instead only does so whenfindIdxandfindIdx?are available. -
#13799 fixes the
alignedtypes and order of the names soWeek.Ordinal.OfMonthnow isWeek.OfMonth.Ordinaland we haveWeek.OfMonth.Aligned.Ordinalthat is a really big type but it express that we can have from 1 to 5 aligned weeks. -
#14180 implements a
DecidableEq Floatinstance, which checks for equality of the underlying bit patterns. -
#14178 teaches grind about the fact that it might be interesting to work with
count a xs = 0 β a β xsoncecount a xsanda β xshave appeared in the e-graph. -
#14116 fixes the deadlock using
Selectable.combineand also fixes a simple problem with recursive mutexes inSelectable.one. This PR fixes #14090 -
#14174 updates the docstrings for
Std.Time.GenericFormat.parseandStd.Time.GenericFormat.parse!to say that they parse intoDateTime, matching their return types. -
#14110 completely rewrites the implementation of
Float.ofScientific. -
#14091 changes the definition of the
FloatandFloat32types to wrap theFloat.Modeltype introduced in #14079. -
#14079 adds types
Float.ModelandFloat32.Modelwhich will serve as logical models for theFloatandFloat32types. -
#14034 adds the Hoare triple lemma
Triple.observetoStd.Do. It proves a triple forprogfrom a specification of a stateless programobs: observing the postconditionQofobs(viah) and usingQto establishwpβ¦progβ§ Post(viahgoal) yieldsβ¦Preβ¦ prog β¦Postβ¦. The premisehprequiresobsto be stateless: its successful runs leave the state unchanged, which holds for every program of a stateless monad such asExcept. -
#14067 adds the weakest-precondition spec lemma
Spec.monadLift_Idso thatmvcgen/mvcgen'can discharge a do-bind that lifts anIdvalue into aPure/WPMonadtransformer stack (for examplelet x β (pure 5 : Id Nat)insideStateT Nat Id). -
#14078 fixes a bug in the
IntX.ofIntClampfamily of functions.
Tactics
-
#14393 implements
grindpropagators that evaluateBitVecoperations on literals -
#14392 adds a new
liaStepsconfiguration option togrind. The motivation is to quickly interrupt the search for hard linear integer arithmetic problems. -
#14390 fixes an issue in the
grindring solver. When a ringRdoes not satisfy[NoNatZeroDivisors R], polynomial simplification could lose information, affecting completeness. -
#14195 extends
vcgenwith automatic frame inference: the@[frameproc]attribute lets a program type register how it frames a resource, andvcgenthen carries that resource across a call without the user specifying an explicitframesclause. Framing is no longer tied to the lattice meet but works for any join-preserving frame operator, so cost budgets, separation-logic footprints, and trace invariants frame through the same mechanism. -
#14379 fixes a bootstrapping issue in the
grindnormalizer. TheBitVec.ofNatLTnormalization theorem must be added to thegrindnormalization set before we processInit/Data/BitVec/Lemmas.lean. Otherwise, patterns are not properly normalized. -
#14373 fixes nontermination in
grindtriggered by constraints of the form0 β£ p. -
#14371 fixes two bugs in
grindcaused by non-normalized bitvector literals.BitVec.ofNatLTliterals and out-of-rangeOfNat.ofNatliterals (e.g.,(17 : BitVec 4)) were not reduced to theOfNat.ofNatnormal form used bygrind, so two representations of the same value were treated as distinct values, andgrindproduced invalid proofs rejected by the kernel:example (x : BitVec 4) (_h1 : x = BitVec.ofNatLT 1 (by decide)) (_h2 : x = 1#4) : True := by grind -- kernel error before this PR
-
#14370 fixes a bug in the
BitVecsimproc whenbitVecOfNat := false. This bug affectsgrindsince it usesbitVecOfNat := false. Here is an example reported by Henrik that exposed the issue. -
#14358 implements a fast path for
grind's internal envelope typeRing.OfSemiring.Q type. -
#14346 optimizes the construction of the
grind-relevant instances for the auxiliarygrindtypeIntModule.OfNatModule.Q. It was a major bottleneck in Mathlib. -
#14314 ensures the
shareCommoninternal cache is reused atrepairAndShare. -
#14299 makes
shareCommonmaintain theSymMrepresentation invariants used bygrindandSym.simp: reducible constants are eagerly unfolded, and kernel projections are folded into projection function applications. These invariants were previously established only by thegrindpreprocessor and were easy to violate from user simprocs and internal code paths (e.g.,Sym.inferTypereturns types from environment signatures that were never preprocessed), producing silent E-matching and indexing failures. Violations are now detected when terms enter the table of maximally shared terms and repaired automatically. -
#14295 lets
vcgenhandle a program wrapped in anmdatanode, such as thesave_infoannotation left behind by spec elaboration, instead of failing with an internal error. -
#14290 makes
int_toBitVecSymM compatible by splitting it into a SymM and a MetaM simp set. Existing users ofint_toBitVecshould now useint_toBitVec_metain theirsimpinvocation instead. -
#14289 ensures that
finish?addsintrosandby_contra, when needed, to the resulting tactic script as preprocessing steps. -
#14287 implements the
rwtactic forsym =>mode. It also breaksLean/Elab/Tatic/Grind/Sym.leaninto smaller files. -
#14137 adds a pointer-equality fast path to the
Sympattern matcher: when a pattern subterm is pointer-equal to the target, it is a closed term equal to the target with no variables to bind, so matching succeeds immediately without traversing the subterm. -
#14281 ensures the RHS of equational theorems is not zeta reduced during preprocessing. This issue was affecting vcgen (see new test by @sgraf812 ).
-
#14280 fixes a bug where
sym => apply <rule>could close a goal with a proof term containing a loose instance metavariable. -
#14279 adds a new
hygienicparameter tointro-like functions inSymM. -
#14278 implements the
case => ..tactic insym =>mode. It is relevant forvcgen(see new test). The new feature tries to simulate thecase => ..tactic in regular tactic mode. -
#14277 fixes spurious
applyfailures inSymM. -
#14241 changes the way that structures are handled by
bv_decide. Previously support for equality of structures inbv_decidewas limited. Now it will use theext_ifflemmas if available and otherwise not reason about equality of structures. This change should increase the reasoning power ofbv_decideon structures. However, this is a breaking change and might require users to annotated previously existing structures with@[ext]or otherwise define and tag extensionality lemmas for them. -
#14227 refactors the way that
bv_decidehandlesUSizeandISize. This is necessary forSymMsupport inbv_decidebecause callingrevertinSymMis illegal. -
#13830 adds automatic
try?suggestions at common proof sites, gated by three options that default to off:-
autoTry.onEmptyProofβ suggests on empty proofs and empty subproofs: emptyby, emptyΒ·, emptycase h =>, and so on. -
autoTry.onUnsolvedGoalβ likeautoTry.onEmptyProof, but also fires on proofs and subproofs that already contain some tactics and left a goal unsolved. The suggestion is appended to the existing sequence (e.g.by skipβby skip; <found>). -
autoTry.onSorryβ suggests onsorrytactics; the suggestion replaces thesorry.
-
-
#14205 stops the
impossibletactic combinator to runcleanupon the goal before negation, as that would defeat the point. -
#13712 makes
exact?,apply?,rw?, andgrind +localsno longer wait for prior async theorem bodies in the same file to finish kernel-checking when iterating the current module's declarations. Before, these tactics walkedenv.constants.mapβ, which forcesenv.checkedand thus blocks on every pending async branch; in an editor session this manifested astry?andexact?appearing to hang near the top of long files. -
#14167 adds a
framesclause to thevcgentactic that attaches a state assertion (a frame) to a matched program, so facts about state the program leaves untouched survive a call whose registered spec drops them. -
#14146 renames the experimental Sym-based
mvcgen'tactic tovcgen, including its grind-mode step, thewithdischarging clause, and thesimplifying_assumptions/until/invariantssyntax. The originalmvcgentactic is unchanged. -
#14142 speeds up
mvcgen'spec lookup by internalizing each matched spec pattern into theSymMshare table on first lookup, so its instance arguments become pointer-equal to the program's and need not be re-internalized on every later lookup. -
#14138 fixes the error message for
mvcegn' ... with <tac>. The main motivation for doing so is when we writemvcgen' with grindthe error message user sees isunexpected identifier; expected grind, which cannot be more confusing. That happens because we except agrindsequence, syntax category for which is calledgrind. I am defining a separate syntax category for discharger tactic calledmvcgenWith, and throw a more meaningful exception if it is a tactic. -
#14134 speeds up
mvcgen'matching by internalizing each backward rule's pattern into theSymMshare table once, when the rule is cached, instead of re-internalizing its instance arguments on every match. -
#14080 extracts a
WPtype class fromWPMonadso that weakest-precondition reasoning andmvcgen'apply to any program type, not only monads. This enables verifying deeply embedded languages: a program type with aWPinstance but noWPMonadinstance, for example an inductive command syntax with its own operational semantics, can now be specified withTripleand decomposed bymvcgen'. -
#14119 fixes
mvcgen/mvcgen'failing to split amatchwhose discriminant telescope is dependent, i.e. when a later discriminant's type mentions an earlier discriminant (such asmatch n, h withwhereh : 0 < n). Abstracting such a matcher previously produced an ill-typed pre-splitter motive. -
#14107 tags
Nat.min_def,Nat.max_def,Int.min_def, andInt.max_defwith the@[lia]attribute, so theliatactic instantiates them via E-matching and can prove goals involvingmin/maxout of the box. This addresses the most common case whereomegacould previously be replaced byliabutliacould not see themin/maxdefinitions, requiring a fall back to the fullgrindtactic. -
#14098 adds a builtin
@[lia]attribute that supplies a small E-matching lemma set to theliatactic. Previouslylia(thecutsat-onlygrindconfiguration) ran with E-matching disabled, so it could not see definitional lemmas such asNat.max_def. Nowliainstantiates only the lemmas tagged@[lia], leaving the much larger@[grind]set disabled. -
#14102 changes the name
WhileInvariantfromStd/Internal/SpecLemmastoRepeatInvariant, since in most of the cases it will be called when verifyingforIn-repeat loops. Also, we add a new abbreviation to constructRepeatInvarinats. This abbreviation specifies a conditioninvwhich should hold at the end of each loop itreation (even the breaking one), and a conditiononDonewhich should hold in the end of the loop in addition toinv. In the case of a normalwhileloop the latter one could always be taken as negation of the loop condition. -
#14099 adds
β€normalisation inmvcgen'. During the run ofmvcgen, in particular when introducing extra state arguments,β€might turn intoβ€ sβ sβ β― sβ. I am adding a procedure which constructs the proof ofβ€ sβ sβ β― sβ = β€on the fly and replaces it. -
#14095 makes
mvcgen'report a clear error when an entailment's assertion lattice is a dependent function type such as(a : Ξ±) β Ξ² a β Prop, instead of looping until it runs out of heartbeats. The order is the ordinary pointwise function order; the limitation is thatmvcgen''s peel ruleLean.Order.le_of_forall_lecannot currently be applied to a dependent function lattice. -
#14081 unifies how
mvcgen'turns@[spec]annotations into backward rules, makes the annotated priority take effect for equational specs, and rejects@[spec]annotations that are neither a Hoare triple, an equation, nor a definition to unfold. -
#14089 lets
mvcgenandmvcgen'apply@[spec]theorems whose statement is a reducible abbreviation wrapping a Hoare triple, such asabbrev foo.spec := β¦Pβ¦ foo β¦Qβ¦. Previously the program stayed stuck because the spec, although registered, was discarded at lookup time. -
#14015 ports the experimental
mvcgen'tactic to the newStd.Internal.Dometa theory, where verification-condition generation works on lattice entailmentspre β wp x post epost. Two changes are visible at the proof surface:mvcgen'now eagerly introduces all state components as local hypotheses, so more facts reachgrind; and loop invariants no longer have to restate the exceptional postcondition.
Compiler
-
#14372 moves
Lean.initializing,enableInitializersExecution, andisInitializerExecutionEnabledtoBaseIOfromIO. -
#14365 ensures that
unsafeterms get properly inlined. Previously having some unsafe termtoccurring inline asunsafe twould create a separate auxiliary declaration that might not end up getting inlined. -
#14343 fixes the new 1GB stack size not being used for the main
leanthread itself, e.g. for serialization or--run. -
#14139 disables symbol stripping of our libleanshared.so in release mode again. As it turns out
--strip-unneededdoesn't only strip symbols that we do not care about. -
#14272 changes
dbgTraceIfSharedto take its message borrowed (s : @& String), with the matchingb_obj_arg/b_lean_obj_argadjustments in the runtime and header. The C implementation only reads the string and never consumed it, so the owned argument leaked on every call; the leak goes unnoticed in typical use because string literals are compiled to persistent constants, which are exempt from reference counting. A dynamically constructed message leaks once per call. Borrowing matches what the implementation actually does and spares callers a reference-count operation. Found while auditing the runtime for the pattern fixed in #14271. -
#13679 fixes an issue where code generation broke when using structures with private fields and types inaccessible in the current scope.
-
#14127 fixes a theoretical but not practical race condition on
lean_task_imp.m_canceledby making it atomic. -
#14108 changes the
m_impfield oflean_taskto an atomic. This is necessary because inget_task_state_corewe access them_impto see if the task is finished before taking the mutex. Thus the memory access as it is done currently is UB.
FFI
-
#14184 exports a
lean_set_initializingsymbol for users of Lean that need to emulate multiplewithImportingcalls from a C FFI.
Documentation
-
#14222 converts a number of comments that seem to have been clearly intended as docstrings into docstrings, avoiding those already converted in #13006.
Server
-
#11958 adjusts the elaborator and snapshot tree system so as not to rerun tactics when whitespace directly following them is changed, preventing loss of progress when preparing to type the next tactic.
-
#14296 makes go-to-definition and find-references work on a
let mutvariable that is referenced after aforloop (or any construct that threads mutable state through a tuple).
Lake
-
#14366 fixes
lake newandlake initto not emit library files on theexetemplate. It also fixes a related bug where the commands could sometimes overwrite library files for existing packages. -
#14300 adds the
presetup,depTrace, anddepHashfacets, which provide different views of a module's full set of dependencies. Also, thesetupfacet is no longer buildable on the CLI (as it produces JSON and not artifacts) and now includes full set of transitive import artifacts, fixing their absence fromlake lean'ssetup.json. -
#14364 adds
getLakeSharedDynlibto the Lake API. It is a simple monadic convenience function that retrievesLakeInstall.sharedDynlibfor the detected Lake installation. -
#14285 makes Lake reconfigure when it cannot read the configuration trace, instead of aborting with
error: compiled configuration is invalid; run with '-R' to reconfigure.importConfigFilealready reconfigures automatically for a stale, wrong-toolchain, or partially-malformed trace; an unparsable trace is no more informative than a missing one, so it is now handled the same way β routed into the sameelabConfig (β acquireTrace h) β¦path β recovering on its own rather than requiring a manual-R. When the trace has no usableoptionsfield it falls back tocfg.lakeOpts, the same options value the fresh-configure branch uses when no trace exists. -
#14284 makes an interrupted Lake configuration recoverable.
importConfigFilewrites the compiled-configuration trace to a buffered handle and then callsIO.FS.Handle.truncateβ which sets the file size but does not flush buffered writes, as its own docstring notes β before the potentially slow configuration elaboration. Alakeprocess killed in that window (an interrupted or cancelled build) leaves the trace on disk as a NUL-byte size placeholder with no.olean, so later invocations fail witherror: compiled configuration is invalid; run with '-R' to reconfigure. Flushing the complete trace before truncating and elaborating means an interruption instead leaves a valid trace and no.olean, which Lake's existing up-to-date check already treats as a trigger to reconfigure automatically. -
#14254 adds two new module facets:
linkInfoExportandlinkInfoNoExport. They provide information on how to link a module. It also providesSyncvariants forbuildSharedLib,buildLeanSharedLib, andbuildLeanExethat work from within aJobrather than across them. -
#14235 makes Lake's module archives (
.ltar) content-stable: byte-identical module outputs now produce a byte-identical archive regardless of the inputs, checkout path, or machine that built them, so input-only changes (e.g. a comment edit in an imported module) upload no new archive bytes and identical outputs deduplicate across revisions on cache services. -
#14206 adapts the deferred docstring check mechanism to use the linter mechanism, presenting an interface akin to that of environment linters. This replaces custom CI setup with an already-used interface. Deferred checks are governed by the option
linter.doc.deferred. -
#14240 ensures executables are executable when restored from the Lake cache even if they were not originally executable in the cache (e.g., because they were downloaded through
lake cache get). -
#14219 adds API for retrieving the complete set of core dynamic libraries. In current terms, these are
libleanshared,libleanshared_1, andlibleanshared_2. andlibInit_shared. These libraries have different interdependencies on Windows and Unix, so they are modelled withDynlibin order to track this information. -
#14220 adds
Dynlib.runtimeOnlyDeps. It specifies transitive dependencies that should not be linked, but need to be preloaded forleanelaboration when precompiling (e.g., libraries dynamically loaded at runtime viadlopen). -
#14156 allows modules which do not depend on any dynamic libraries to toggle
platformIndependentbetweentrueand unset without a rebuild. -
#14130 fixes
Package.remoteUrl?so an emptyremoteUrlreturnsnoneand a non-emptyremoteUrlreturnssome remoteUrl. -
#13646 adds a new Lake package option
requiresModuleSystem. When a package sets it totrue, Lake emits a warning whenever a non-module-system file (one without amoduleheader) imports a module of the package, both from downstream consumers and from non-module files within the package itself. This signals that the package's API expects the visibility and elaboration semantics of the module system. A companion optionallowNonModuleslets an importing package opt out of these warnings, declaring that it knowingly mixes non-module-system files with module-system dependencies.