Lean 4.21.0-rc3
(These are the preliminary release notes for v4.21.0-rc3
.)
For this release, 295 changes landed. In addition to the 100 feature additions and 83 fixes listed below there were 2 refactoring changes, 4 documentation improvements, 6 performance improvements, 2 improvements to the test suite and 98 other changes.
Highlights
'Unknown identifier' code actions
-
#7665 and #8180 add support for code actions that resolve 'unknown identifier' errors by either importing the missing declaration or by changing the identifier to one from the environment.
New Language Features
-
#8449 and #8516 upstream and extend the Mathlib
clear_value
tactic. Given a local definitionx : T := v
, the tacticclear_value x
replaces it with a hypothesisx : T
, or throws an error if the goal does not depend on the valuev
. The syntaxclear_value (h : x = _)
creates a hypothesish : x = _
before clearing the value ofx
. Any expression definitionally equal tox
can be used in place of the underscore. Furthermore,clear_value *
clears all values that can be cleared, or throws an error if none can be cleared. -
#8512 adds a
value_of% ident
term that elaborates to the value of the local or global constantident
. This is useful for creating definition hypotheses:let x := ... complicated expression ... have hx : x = value_of% x := rfl
-
#8450 adds a feature to the
subst
tactic so that whenx : X := v
is a local definition,subst x
substitutesv
forx
in the goal and removesx
. Previously the tactic would throw an error. -
#8037 introduces a
noConfusionType
construction that’s sub-quadratic in size, and reduces faster. The previousnoConfusion
construction with two nestedmatch
statements is quadratic in size and reduction behavior. Using some helper definitions, a linear size construction is possible. -
#8104 makes
fun_induction
andfun_cases
(try to) unfold the function application of interest in the goal. The old behavior can be enabled withset_option tactic.fun_induction.unfolding false
. Forfun_cases
this does not work yet when the function’s result type depends on one of the arguments, see issue #8296. -
#8171 omits cases from functional induction/cases principles that are implemented
by contradiction
(or, more generally,False.elim
,absurd
or `noConfusion). Breaking change in the sense that there are fewer goals to prove after using functional induction. -
#8106 adds a
register_linter_set
command for declaring linter sets. ThegetLinterValue
function now checks if the present linter is contained in a set that has been enabled (using theset_option
command or on the command line). -
#8267 makes
#guard_msgs
to treattrace
messages separate frominfo
,warning
anderror
. It also introduces the ability to say#guard_msgs (pass info)
, like(drop info)
so far, and also adds(check info)
as the explicit form of(info)
, for completeness.
Library Highlights
-
#8358 introduces a very minimal version of the new iterator library. It comes with list iterators and various consumers, namely
toArray
,toList
,toListRev
,ForIn
,fold
,foldM
anddrain
. All consumers also come in a partial variant that can be used without any proofs. This limited version of the iterator library generates decent code, even with the old code generator. -
#7352 reworks the
simp
set around theId
monad, to not elide or unfoldpure
andId.run
-
#8313 changes the definition of
Vector
so it no longer extendsArray
. This preventsArray
API from "leaking through".
Other Highlights
-
Performance optimizations in
dsimp
:-
#6973 stops
dsimp
from visiting proof terms, which should makesimp
anddsimp
more efficient. -
#7428 adds a
dsimp
cache tosimp
. Previously eachdsimp
call fromsimp
started with a fresh cache. As a result, time spent insimp
while compiling Mathlib is reduced by over 45%, giving an overall 8% speedup to Mathlib compilation.
-
-
#8221 adjusts the experimental module system to not export the bodies of
def
s unless opted out by the new attribute@[expose]
on thedef
or on a surroundingsection
. -
#8559 and #8560 fix an adversarial soundness attack described in #8554. The attack exploits the fact that
assert!
no longer aborts execution, and that users can redirect error messages.
Language
-
#6973 stops
dsimp
from visiting proof terms, which should makesimp
anddsimp
more efficient. -
#7428 adds a
dsimp
cache tosimp
. Previously eachdsimp
call fromsimp
started with a fresh cache. As a result, time spent insimp
while compiling Mathlib is reduced by over 45%, giving an overall 8% speedup to Mathlib compilation. -
#7631 fixes
Lean.Level.mkIMaxAux
(mk_imax
in the kernel) such thatimax 1 u
reduces tou
. -
#7977 adds basic support for eta-reduction to
grind
. -
#8002 fixes an issue where "go to definition" for variables generalized by the
induction
andcases
tactic did not work. Closes #2873. -
#8024 adds the
--setup
option to thelean
CLI. It takes a path to a JSON file containing information about a module's imports and configuration, superseding that in the module's own file header. This will be used by Lake to specify paths to module artifacts (e.g., oleans and ileans) separate from theLEAN_PATH
schema. -
#8037 introduces a
noConfusionType
construction that’s sub-quadratic in size, and reduces faster. -
#8104 makes
fun_induction
andfun_cases
(try to) unfold the function application of interest in the goal. The old behavior can be enabled withset_option tactic.fun_induction.unfolding false
. Forfun_cases
this does not work yet when the function’s result type depends on one of the arguments, see issue #8296. -
#8106 adds a
register_linter_set
command for declaring linter sets. ThegetLinterValue
function now checks if the present linter is contained in a set that has been enabled (using theset_option
command or on the command line). -
#8169 makes the whitespace handling in the syntax of
omit
andinclude
consistent withvariable
. -
#8171 omits cases from functional induction/cases principles that are implemented
by contradiction
(or, more generally,False.elim
,absurd
or `noConfusion). Breaking change in the sense that there are fewer goals to prove after using functional induction. -
#8196 improves the E-matching pattern inference procedure in
grind
. Consider the following theorem:@[grind →] theorem eq_empty_of_append_eq_empty {xs ys : Array α} (h : xs ++ ys = #[]) : xs = #[] ∧ ys = #[] := append_eq_empty_iff.mp h
Before this PR,
grind
inferred the following pattern:@HAppend.hAppend _ _ _ _ #2 #1
Note that this pattern would match any
++
application, even if it had nothing to do with arrays. With this PR, the inferred pattern becomes:@HAppend.hAppend (Array #3) (Array _) (Array _) _ #2 #1
With the new pattern, the theorem will not be considered by
grind
for goals that do not involveArray
s. -
#8198 fixes an issue in the theory propagation used in
grind
. When two equivalence classes are merged, the core may need to push additional equalities or disequalities down to the satellite theory solvers (e.g.,cutsat
,comm ring
, etc). Some solvers (e.g.cutsat
) assume that all of the core’s invariants hold before they receive those facts. Propagating immediately therefore risks violating a solver’s pre-conditions midway through the merge. To decouple the merge operation from propagation and to keep the core solver-agnostic, this PR adds the helper typePendingTheoryPropagation
. -
#8208 reduces the need for defeq in frequently used bv_decide rewrite by turning them into simprocs that work on structural equality instead. As the intended meaning of these rewrites is to simply work with structural equality anyways this should not change the proving power of
bv_decide
's rewriter but just make it faster on certain very large problems. -
#8209 fixes a nondeterminism issue in the
grind
tactic. It was a bug in the model-based theory combination module. -
#8221 adjusts the experimental module system to not export the bodies of
def
s unless opted out by the new attribute@[expose]
on thedef
or on a surroundingsection
. -
#8224 adds diagnostic information for the commutative ring procedure in
grind
. -
#8226 fixes the
simplifyBasis
procedure in the commutative ring procedure ingrind
. -
#8231 changes the behaviour of
apply?
so that thesorry
it uses to close the goal is non-synthetic. (Recall that correct use of synthetic sorries requires that the tactic also generates an error message, which we don't want to do in this situation.) This change defends against the problem reported in #8212. -
#8232 fixes elaboration of constants in the
rewrite
tactic. previously,rw [eq_self]
would elaborateeq_self
twice, and add it to the infotree twice. This would lead to the "Expected type" being delaborated with an unknown universe metavariable. -
#8241 changes the behavior of the
rename
tactic to skip over implementation detail hypotheses when finding a hypothesis to rename. -
#8254 fixes unintended inlining of
ToJson
,FromJson
, andRepr
instances, which was causing exponential compilation times inderiving
clauses for large structures. -
#8259 clarifies the invalid field notation error when projected value type is a metavariable.
-
#8260 clarifies the invalid dotted identifier notation error when the type is a sort.
-
#8261 adjusts the error message when
apply
fails to unify. It is clearer about distinguishing the term being applied and the goal, as well as distinguishing the "conclusion" of the given term and the term itself. -
#8262 improves the type-as-hole error message. Type-as-hole error for theorem declarations should not admit the possibility of omitting the type entirely.
-
#8264 rewords the
application type mismatch
error message by more specifically mentioning that the problem is with the final argument. This is useful when the same argument is passed to the function multiple times. -
#8267 makes
#guard_msgs
to treattrace
messages separate frominfo
,warning
anderror
. It also introduce the ability to say#guard_msgs (pass info
, like(drop info)
so far, and also adds(check info)
as the explicit form of(info)
, for completeness. -
#8270 makes the enum pass of
bv_decide
handle enum types that are universe polymorphic. -
#8271 changes
addPPExplicitToExposeDiff
to show universe differences and to visit into projections, e.g.:error: tactic 'rfl' failed, the left-hand side (Test.mk (∀ (x : PUnit.{1}), True)).1 is not definitionally equal to the right-hand side (Test.mk (∀ (x : PUnit.{2}), True)).1
for
inductive Test where | mk (x : Prop)
-
#8275 ensures the congruence closure in
grind
and find non-dependent arrow congruences. That is, it can apply theimplies_congr
theorem. -
#8276 adds the instances
Grind.CommRing (Fin n)
andGrind.IsCharP (Fin n) n
. New tests:example (x y z : Fin 13) : (x + y + z) ^ 2 = x ^ 2 + y ^ 2 + z ^ 2 + 2 * (x * y + y * z + z * x) := by grind +ring
-
#8277 improves the generation of
.induct_unfolding
by rewritingmatch
statements more reliably, using the new “congruence equations” introduced in #8284. Fixes #8195. -
#8280 the support for arrows in the congruence closure procedure used in
grind
. -
#8281 improves the module used to prove auxiliary type cast equalities in
grind
. -
#8284 adds a new variant of equations for matchers, namely “congruence equations” that generalize the normal matcher equations. They have unrestricted left-hand-sides, extra equality assumptions relating the discriminiants with the patterns and thus prove heterogenous equalities. In that sense they combine congruence with rewriting. They can be used to rewrite matcher applications where, due to dependencies,
simp
would fail to rewrite the discriminants, and will be used when producing the unfolding induction theorems. -
#8285 fixes “declaration has free variables” errors when generating a splitter for a match statement with named patterns. Fixes #8274.
-
#8299 implements a missing preprocessing step in
grind
: abstract metavariables in the goal -
#8301 unfolds functions in the unfolding induction principle properly when they use
bif
(a.k.a.Bool.cond
). -
#8302 lets
cases
fail gracefully when the motive has an complex argument whose type is dependent type on the targets. While theinduction
tactic can handle this well,cases
does not. This change at least gracefully degrades to not instantiating that motive parameter. See issue #8296 for more details on this issue. -
#8303 fixes missing occurrences of
foldProjs
ingrind
. -
#8306 makes it possible for
bv_decide
to tackle situations for its enum type preprocessing where the enums themselves are use in a dependently type context (for example inside of aGetElem
body) and thus not trivially accessible tosimp
for rewriting. To do this we dropGetElem
onBitVec
as well asdite
as early as possible in the pipeline. -
#8321 lets the termination argument inference consider negations of Nat comparisons. Fixes #8257.
-
#8323 adds support for bv_decide to understand
BitVec.reverse
in bitblasting. -
#8330 improves support for structure extensionality in
grind
. It now uses eta expansion for structures instead of the extensionality theorems generated by[ext]
. Examples:opaque f (a : Nat) : Nat × Bool
-
#8338 improves the error messages displayed in
inductive
declarations when type parameters are invalid or absent. -
#8341 fixes the
propagateCtor
constraint propagator used ingrind
. -
#8343 splits
Lean.Grind.CommRing
into 4 typeclasses, for semirings and noncommutative rings. This does not yet change the behaviour ofgrind
, which expects to find all 4 typeclasses. Later we will make some generalizations. -
#8344 fixes term normalization issues in
grind
, and the new optiongrind +etaStruct
. -
#8347 adds draft typeclasses for
grind
to process facts about ordered modules. These interfaces will evolve as the implementation develops. -
#8354 makes sure that when generating the unfolding functional induction theorem,
mdata
does not get in the way. -
#8356 tries harder to clean internals of the argument packing of n-ary functions from the functional induction theorem, in particular the unfolding variant
-
#8359 improves the functional cases principles, by making a more educated guess which function parameters should be targets and which should remain parameters (or be dropped). This simplifies the principles, and increases the chance that
fun_cases
can unfold the function call. -
#8361 fixes a bug in the
cases
tacic introduced in #3188 that arises when cases (not induction) is used with a non-atomic expression in using and the argument indexing gets confused. -
#8363 unifies various ways of naming auxiliary declarations in a conflict-free way and ensures the method is compatible with diverging branches of elaboration such as parallelism or Aesop-like backtracking+replaying search.
-
#8365 fixes the transparency mode for ground patterns. This is important for implicit instances. Here is a mwe for an issue detected while testing
grind
in Mathlib.example (a : Nat) : max a a = a := by grind
-
#8368 improves the error messages produced by invalid pattern-match alternatives and improves parity in error placement between pattern-matching tactics and elaborators.
-
#8369 fixes a type error at
instantiateTheorem
function used ingrind
. It was failing to instantiate theorems such astheorem getElem_reverse {xs : Array α} {i : Nat} (hi : i < xs.reverse.size) : (xs.reverse)[i] = xs[xs.size - 1 - i]'(by simp at hi; omega)
in examples such as
example (xs : Array Nat) (w : xs.reverse = xs) (j : Nat) (hj : 0 ≤ j) (hj' : j < xs.size / 2) : xs[j] = xs[xs.size - 1 - j]
generating the issue
[issue] type error constructing proof for Array.getElem_reverse when assigning metavariable ?hi with ‹j < xs.toList.length› has type j < xs.toList.length : Prop but is expected to have type j < xs.reverse.size : Prop
-
#8375 ensures that using
mapError
to expand an error message usesaddMessageContext
to include the current context, so that expressions are rendered correctly. Also adds apreprendError
variant with a more convenient argument order for the common cases of prepending-and-indenting. -
#8403 adds missing monotonicity lemmas for universal quantifiers, that are used in defining (co)inductive predicates.
-
#8410 fixes a case-splitting heuristic in
grind
and simplifies the proof for testgrind_palindrome2.lean
. -
#8412 fixes the
markNestedProofs
preprocessor used ingrind
. There was a missing case (e.g.,Expr.mdata
) -
#8413 implements normalization rules that pull universal quantifiers across disjunctions. This is a common normalization step performed by first-order theorem provers.
-
#8417 introduces
Lean.Grind.Field
, proves that aIsCharP 0
field satisfiesNoNatZeroDivisors
, and sets up some basic (currently failing) tests forgrind
. -
#8426 adds the attribute
[grind?]
. It is like[grind]
but displays inferred E-matching patterns. It is a more convinient than writing. Thanks @kim-em for suggesting this feature.set_option trace.grind.ematch.pattern true
also improves some tests, and adds helper function
ENode.isRoot
. -
#8429 adds
Lean.Grind.Ring.IsOrdered
, and cleans up the ring/module grind API. These typeclasses are at present unused, but will support future algorithmic improvements ingrind
. -
#8437 fixes
split
in the presence of metavariables in the target. -
#8438 ensures that
grind
diagnostics are obtained even whenmaxHeartbeats
is reached. also removes some dead code. -
#8440 implements non-chronological backtracking for the
grind
tactic. This feature ensures thatgrind
does not need to process irrelevant branches after performing a case-split that is not relevant. It is not just about performance, but also the size of the final proof term. The new test demonstrates this feature in practice.-- In the following test, the first 8 case-splits are irrelevant, -- and non-choronological backtracking is used to avoid searching -- (2^8 - 1) irrelevant branches /-- trace: [grind.split] p8 ∨ q8, generation: 0 [grind.split] p7 ∨ q7, generation: 0 [grind.split] p6 ∨ q6, generation: 0 [grind.split] p5 ∨ q5, generation: 0 [grind.split] p4 ∨ q4, generation: 0 [grind.split] p3 ∨ q3, generation: 0 [grind.split] p2 ∨ q2, generation: 0 [grind.split] p1 ∨ q1, generation: 0 [grind.split] ¬p ∨ ¬q, generation: 0 -/ #guard_msgs (trace) in set_option trace.grind.split true in theorem ex : p ∨ q → ¬ p ∨ q → p ∨ ¬ q → ¬ p ∨ ¬ q → p1 ∨ q1 → p2 ∨ q2 → p3 ∨ q3 → p4 ∨ q4 → p5 ∨ q5 → p6 ∨ q6 → p7 ∨ q7 → p8 ∨ q8 → False := by grind (splits := 10)
-
#8443 adds the lemmas about ordered rings and ordered fields which will be needed by the new algebraic normalization components of
grind
. -
#8449 upstreams and extends the Mathlib
clear_value
tactic. Given a local definitionx : T := v
, the tacticclear_value x
replaces it with a hypothesisx : T
, or throws an error if the goal does not depend on the valuev
. The syntaxclear_value x with h
creates a hypothesish : x = v
before clearing the value ofx
. Furthermore,clear_value *
clears all values that can be cleared, or throws an error if none can be cleared. -
#8450 adds a feature to the
subst
tactic so that whenx : X := v
is a local definition,subst x
substitutesv
forx
in the goal and removesx
. Previously the tactic would throw an error. -
#8466 fixes another instance of the
grind
issue "unexpected kernel projection term during internalization". -
#8472 avoids name resolution blocking on the elaboration of a theorem's proof when looking up the theorem name.
-
#8479 implements hash-consing for
grind
that takes alpha equivalence into account. -
#8483 ensures
grind
reuses thesimp
cache between different calls. Recall thatgrind
usessimp
to normalize terms during internalization. -
#8491 fixes the behavior of
simp_all?
andsimp_all?!
, aligning them withsimp_all
andsimp_all!
respectively. -
#8506 implements
match
-expressions ingrind
usingmatch
congruence equations. The goal is to minimize the number ofcast
operations that need to be inserted, and avoidcast
over functions. The new approach supportmatch
-expressions of the formmatch h : ... with ...
. -
#8512 adds a
value_of% ident
term that elaborates to the value of the local or global constantident
. This is useful for creating definition hypotheses:let x := ... complicated expression ... have hx : x = value_of% x := rfl
-
#8516 is a followup to #8449 to refine the syntax of
clear_value
. The syntax for adding equality hypotheses before clearing values is nowclear_value (h : x = _)
. Any expression definitionally equal tox
can be used in place of the underscore. -
#8536 fixes the support for
LawfulBEq
andBEq
ingrind
. -
#8541 ensures that for any nested proof
h : p
in a goal, we propagate thatp
is true in thegrind
tactic. -
#8542 fixes two inappropriate uses of
whnfD
ingrind
. They were potential performance foot guns, and were producing unexpected errors sincewhnfD
is not consistently used (and it should not be) in all modules. -
#8544 implements support for over-applied
ite
anddite
applications in thegrind
tactic. It adds support for propagation and case-split. -
#8549 fixes the hash function used to implement congruence closure in
grind
. The hash of anExpr
must not depend on whether the expression has been internalized or not. -
#8564 simplifies the interface between the
grind
core and the cutsat procedure. Before this PR, core would try to minimize the number of numeric literals that have to be internalized in cutsat. This optimization was buggy (seegrind_cutsat_zero.lean
test), and produced counterintuitive counterexamples. -
#8569 adds support for generalized E-match patterns to arbitrary theorems.
-
#8570 fixes some issues in the E-matching generalized pattern support after the update stage0.
-
#8572 adds some generalized
Option
theorems forgrind
. The avoidcasts
operations during E-matching. -
#8576 sets
ring := true
by default ingrind
. It also fixes a bug in the reification procedure, and improves the term internalization in the ring and cutsat modules.
Library
-
#7352 reworks the
simp
set around theId
monad, to not elide or unfoldpure
andId.run
-
#7995 adds a verification of
Array.qsort
properties, trying to usegrind
andfun_induction
where possible. Currently this is in thetests/
folder, but oncegrind
is ready for production use we will move it out into the library. -
#8182 adds
ofList_eq_insertMany_empty
lemmas for all the hash/tree map types, with the exception ofStd.HashSet.Raw.ofList_eq_insertMany_empty
. -
#8188 takes the existing
getElem_map
statements forHashMap
variants (alsogetElem?
,getElem!
, andgetD
statements), adds a prime to their name and an explanatory comment, and replaces the unprimed statement with a simpler statement that is only true withLawfulBEq
present. The original statements which were simp lemmas are now low priority simp lemmas, so the nicer statements should fire whenLawfulBEq
is available. -
#8202 adds an inference that was repeatedly needed when proving
BitVec.msb_sdiv
, and is the symmetric version ofBitVec.one_eq_zero_iff
-
#8206 shows that negating a bitvector created from a natural number equals creating a bitvector from the the negative of that number (as an integer).
-
#8216 completes adding
@[grind]
annotations forOption
lemmas, and incidentally fills in someOption
API gaps/defects. -
#8218 continues adding
@[grind]
attributes for List/Array/Vector, particularly to the lemmas involving thetoList
/toArray
functions. -
#8246 add
@[grind]
annotations for HashMap and variants. -
#8272 adds lemmas about the length and use of
[]?
on results ofList.intersperse
. -
#8291 changes the statements of
Fin
lemmas to use[NeZero n] (i : Fin n)
rather than(i : Fin (n+1))
where possible. -
#8298 adds various
Option
lemmas and definesOption.filterM
for applicative functors. -
#8313 changes the definition of
Vector
so it no longer extendsArray
. This preventsArray
API from "leaking through". -
#8315 splits
Std.Classes.Ord
intoStd.Classes.Ord.Basic
(with few imports) andStd.Classes.Ord.SInt
andStd.Classes.Ord.Vector
. These changes avoid importingInit.Data.BitVec.Lemmas
unnecessarily into various basic files. As the new import-only fileStd.Classes.Ord
imports all three of these, end-users are not affected. -
#8318 is follow-up to #8272, combining the conditional lemmas for
getElem_intersperse
into a single lemma with anif
on the RHS. -
#8327 adds
@[grind]
annotations to the genericgetElem?_eq_none_iff
,isSome_getElem?
, andget_getElem?
. -
#8328 adds the
@[grind =]
attribute to allcontains_iff_mem
lemmas. -
#8331 improves the docstring for
PlainDateTime.now
and its variants. -
#8346 adds some missing lemmas about consequences of positivity/non-negativity of
a * b : Int
. -
#8349 fixes the signature of the intended
Inhabited
instance forExtDHashMap
. -
#8357 adds variants of
dite_eq_left_iff
that will be useful in a future PR. -
#8358 introduces a very minimal version of the new iterator library. It comes with list iterators and various consumers, namely
toArray
,toList
,toListRev
,ForIn
,fold
,foldM
anddrain
. All consumers also come in a partial variant that can be used without any proofs. This limited version of the iterator library generates decent code, even with the old code generator. -
#8378 improves and extends the api around
Ord
andOrdering
. -
#8379 adds missing
Option
lemmas. -
#8380 provides simple lemmas about
toArray
,toList
andtoListRev
for the iterator library. -
#8384 provides lemmas about the behavior of
step
,toArray
,toList
andtoListRev
on list iterators created withList.iter
andList.iterM
. -
#8389 adds the
List/Array/Vector.ofFnM
, the monadic analogues ofofFn
, along with basic theory. -
#8392 corrects some
Array
lemmas to be aboutArray
notList
. -
#8397 cleans up many duplicate instances (or, in some cases, needlessly duplicated
def X := ...; instance Y := X
). -
#8399 adds variants of
HashMap.getElem?_filter
that assumeLawfulBEq
and have a simpler right-hand-side.simp
can already achieve these, via rewriting withgetKey_eq
under the lambda. Howevergrind
can not, and these lemmas helpgrind
work withHashMap
goals. There are variants for all variants ofHashMap
,getElem?/getElem/getElem!/getD
, and forfilter
andfilterMap
. -
#8405 provides lemmas about the loop constructs
ForIn
,fold
,foldM
anddrain
and their relation to each other in the context of iterators. -
#8418 provides the
take
iterator combinator that transforms any iterator into an iterator that stops after a given number of steps. The change contains the implementation and lemmas. -
#8422 adds
LT
andDecidable
LT
instances forStd.Time.Timestamp
andStd.Time.Duration
. -
#8434 adds the equivalent of
List.take_cons
aboutList.drop
. -
#8435 upstreams the
LawfulMonadLift(T)
classes, lemmas and instances from Batteries into Core because the iterator library needs them in order to prove lemmas about themapM
operator, which relies onMonadLiftT
. -
#8445 adds a
@[simp]
lemma, and comments explaining that there is intentionally no verification API forVector.take
,Vector.drop
, orVector.tail
, which should all be rewritten in terms ofVector.extract
. -
#8446 adds basic
@[grind]
annotations forTreeMap
and its variants. Likely more annotations will be added after we've explored some examples. -
#8451 provides the iterator combinator
filterMap
in a pure and monadic version and specializationsmap
andfilter
. This new combinator allows to apply a function to the emitted values of a stream while filtering out certain elements. -
#8460 adds further
@[grind]
annotations forOption
, as follow-up to the recent additions to theOption
API in #8379 and #8298. -
#8465 adds further lemmas about
LawfulGetElem
, including marking some with@[grind]
. -
#8470 adds
@[simp]
togetElem_pos/neg
(similarly forgetElem!
). These are often already simp lemmas for concrete types. -
#8482 adds preliminary
@[grind]
annotations forList.Pairwise
andList.Nodup
. -
#8484 provides the iterator combinator
zip
in a pure and monadic version. -
#8492 adds
simp
lemmas fortoInt_*
andtoNat_*
with arithmetic operation given the hypothesis of no-overflow (toNat_add_of_not_uaddOverflow
,toInt_add_of_not_saddOverflow
,toNat_sub_of_not_usubOverflow
,toInt_sub_of_not_ssubOverflow
,toInt_neg_of_not_negOverflow
,toNat_mul_of_not_umulOverflow
,toInt_mul_of_not_smulOverflow
). In particular, these aresimp
since (1) therhs
is strictly simpler than thelhs
and (2) this version is also simpler than the standard operation when the hypothesis is available. -
#8493 provides the iterator combinators
takeWhile
(forwarding all emitted values of another iterator until a predicate becomes false)dropWhile
(dropping values until some predicate on these values becomes false, then forwarding all the others). -
#8497 adds preliminary grind annotations for
List.Sublist
/IsInfix
/IsPrefix
/IsSuffix
, along with test cases. -
#8499 changes the definition of
Array.ofFn.go
to use recursion onNat
(rather than well-founded recursion). This resolves a problem reported on zulip). -
#8513 removes the
@[reducible]
annotation onArray.size
. This is probably best gone anyway in order to keep separation between theList
andArray
APIs, but it also helps avoid uselessly instantiatingArray
theorems whengrind
is working onList
problems. -
#8515 removes the prime from
Fin.ofNat'
: the oldFin.ofNat
has completed its 6 month deprecation cycle and is being removed. -
#8527 adds
grind
annotations for theorems aboutList.countP
andList.count
. -
#8552 provides array iterators (
Array.iter(M)
,Array.iterFromIdx(M)
), infinite iterators produced by a step function (Iter.repeat
), and aForM
instance for finite iterators that is implemented in terms ofForIn
. -
#8620 removes the
NatCast (Fin n)
global instance (both the direct instance, and the indirect one viaLean.Grind.Semiring
), as that instance causes causesx < n
(forx : Fin k
,n : Nat
) to be elaborated asx < ↑n
rather than↑x < n
, which is undesirable. Note however that in Mathlib this happens anyway!
Compiler
-
#8211 adds support for generating IR from the LCNF representation of the new compiler.
-
#8236 fixes an issue where the combination of
extern_lib
andprecompileModules
would lead to "symbol not found" errors. -
#8268 optimizes lean_nat_shiftr for scalar operands. The new compiler converts Nat divisions into right shifts, so this now shows up as hot in some profiles.
-
#8308 makes the new compiler's specialization pass compute closures the same way as the old compiler, in particular when it comes to variables captured by lambdas.
-
#8367 adds a new
structProjCases
pass to the new compiler, analogous to thestruct_cases_on
pass in the old compiler, which converts all projections from structs intocases
expressions. When lowered to IR, this causes all of the projections from a single structure to be grouped together, which is an invariant relied upon by the IR RC passes (at least for linearity, if not general correctness). -
#8409 adds support to LCNF for native UInt8/UInt16/UInt32/UInt64 literals.
-
#8456 adds support for primitive USize literals in LCNF.
-
#8458 adds closed term extraction to the new compiler, closely following the approach in the old compiler. In the future, we will explore some ideas to improve upon this approach.
-
#8462 enables the LCNF extractClosed pass by default.
-
#8468 switches the LCNF baseExt/monoExt environment extensions to use a custom environment extension that uses a PersistentHashMap. The optimizer relies upon the ability to update a decl multiple times, which does not work with SimplePersistentEnvExtension.
-
#8502 changes the new compiler to use the kernel environment to find definitions, which causes compilation to be skipped when the decl had a kernel error (e.g. due to an unresolved metavariable). This matches the behavior of the old compiler.
-
#8521 makes LCNF.toMono recursively process jmp args.
-
#8523 moves the new compiler's noncomputable check into toMono, matching the recent change in the old compiler. This is mildly more complicated because we can't throw an error at the mere use of a constant, we need to check for a later relevant use. This is still a bit more conservative than it could theoretically be around join points and local functions, but it's hard to imagine that mattering in practice (and we can easily enable it if it does).
-
#8535 extracts more Nats (and their downstream users) in extractClosed by fixing a silly oversight in the logic.
-
#8540 changes the LCNF specialize pass to allow ground variables to depend on local fun decls (with no non-ground free variables). This enables specialization of Monad instances that depend on local lambdas.
-
#8559 fixes an adversarial soundness attack described in #8554. The attack exploits the fact that
assert!
no longer aborts execution, and that users can redirect error messages. Another PR will implement the same fix forExpr.Data
. -
#8560 is similar to #8559 but for
Expr.mkData
. This vulnerability has not been exploited yet, but adversarial users may find a way. -
#8561 increases maxHeartbeats in the isDefEqProjIssue test, because when running under the new compiler the
run_meta
call includes the allocations of the compiler itself. With the old compiler, many of the corresponding allocations were internal to C++ code and would not increase the heartbeat count. -
#8565 makes the LCNF specialization pass only treat type/instance params as ground vars. The current policy was too liberal and would result on computations being floated into specialized loops.
-
#8566 changes the LCNF constant folding pass to not convert Nat multiplication to a left shift by a power of 2. The fast path test for this is sufficiently complex that it's simpler to just use the fast path for multiplication.
-
#8575 makes LCNF's simpAppApp? bail out on trivial aliases as intended. It seems that there was a typo in the original logic, and this PR also extends it to include aliases of global constants rather than just local vars.
-
#8582 fixes an accidental dropping of state in Param.toMono. When this code was originally written, there was no other state besides
typeParams
.
Pretty Printing
-
#8041 changes the behavior of
pp.showLetValues
to use a hoverable⋯
to hide let values. This is now false by default, and there is a new optionpp.showLetValues.threshold
for allowing small expressions to be shown anyway. For tactic metavariables, there is an additional optionpp.showLetValues.tactic.threshold
, which by default is set to the maximal value, since in tactic states local values are usually significant. -
#8372 modifies the pretty printer to use
have
syntax instead oflet_fun
syntax. -
#8457 fixes an issue when including a hard line break in a
Format
that caused subsequent (ordinary) line breaks to be erroneously flattened to spaces. -
#8504 modifies the pretty printer so that dot notation is used for class parent projections. Previously, dot notation was never used for classes.
Documentation
-
#8199 adds a style guide for documentation, including both general principles and docstring-specific concerns.
Server
-
#7665 and #8180 add support for code actions that resolve 'unknown identifier' errors by either importing the missing declaration or by changing the identifier to one from the environment.
-
#8091 improves the performance of the workspace symbol request.
-
#8242 fixes the 'goals accomplished' diagnostics. They were accidentally broken in #7902.
-
#8350 changes namespace completion to use the same algorithm as declaration identifier completion, which makes it use the short name (last name component) for completions instead of the full name, avoiding namespace duplications.
-
#8362 fixes a bug where the unknown identifier code actions wouldn't work correctly for some unknown identifier error spans and adjusts several unknown identifier spans to actually end on the identifier in question.
Lake
-
#8383 fixes the use of
import Lake
with precompiled modules, which was previously broken on MacOS. -
#8411 fixes a doc bug in the Resolve.lean; in reverse order, B comes before A
-
#8528 fixes the heuristic Lake uses to determine whether a
lean_lib
can be loaded vialean --plugin
rather thanlean --load-dynlib
. Previously, a mismatch between the single root's name and the library's name would not be caught and cause loading to fail. -
#8529 changes
lake lean
andlake setup-file
to precompile the imports of non-workspace files using the the import's whole library. This ensures that additional link objects are linked and available during elaboration. -
#8539 changes Lake to use relative path for the Lean messages produced by a module build. This makes the message portable across different machines, which is useful for Mathlib's cache.
Other
