Lean4.33.0 (2026-08-10)
此版本有 208 项更改。 除了新增的 53 项功能外, 以及下面列出的 50 个修复, 有 12 处重构更改, 11 项文档改进, 21 项性能改进, 对测试套件的 6 项改进, 以及 55 个其他变化。
亮点
Lean 4.33.0 专注于响应能力和整合:编辑器在您打字时保留更多工作,try? 可以自行提出证明,lia 和 grind 策略得到改进,Float 不再是不透明的类型。继续 v4.31.0 的透明工作,它还默认启用 backward.isDefEq.respectTransparency.types — 这是移植时最可能需要注意的更改。
此亮点部分由 Juanjo Madrigal 贡献。
响应速度更快的编辑器
几项独立的更改使交互式编辑明显更加流畅:
-
#11958 防止精译器仅因策略之后的空白发生变化而重新运行该策略。在策略后按回车准备下一行时,不再丢弃其后全部内容已取得的进度。
-
#13712 使
exact?、apply?、rw?和grind +locals停止等待同一文件中的早期定理来完成内核检查。在编辑器会话中,这通常显示为try?和exact?,似乎挂在长文件的顶部附近。 -
#14234 使完成、悬停和交互式术语目标看到术语级
open … in或set_option … in范围的开放命名空间和选项,而不是封闭命令的开放命名空间和选项。 -
#14296 恢复在
for循环之后引用的let mut变量上的转到定义和查找引用。
诊断也变得更加可行。 unusedVariables 检查器现在提供下划线重命名作为适用的提示 (#14259):
def constantly (n : Nat) : Nat := 0
新的检查器会警告 open 实际上不会打开以给定名称 (#14325) 结尾的每个命名空间:在 namespace A 内部,一旦上游 A.B 出现,open B 就会停止到达 _root_.B,这解释了随后出现的令人费解的 unknown identifier 错误。最后,#14196 澄清了有关可还原性属性的警告。
自动 try? 建议
#13830 让 try? 在缺少证明的情况下自行运行,由三个默认关闭的选项控制:
-
autoTry.onEmptyProof— 一个空的by、一个空的·、一个空的case h =>,依此类推。 -
autoTry.onUnsolvedGoal— 与上面类似,但也会在已经包含策略并留下目标的证据上触发;该建议被附加到已写的内容中。 -
autoTry.onSorry—sorry,建议将其替换。
set_option autoTry.onEmptyProof true in
example (a b : Nat) : a + b = b + a := by
策略改进
lia 在禁用电子匹配的情况下运行,因此它看不到定义引理。 #14098 给它自己的 @[lia] 集——远小于 @[grind],它保持禁用状态——并且 #14107 标记 min/max 定义,结束了 omega 不能简单地被 lia 替换的最常见情况:
example (a b : Nat) : min a b ≤ max a b := a:Natb:Nat⊢ min a b ≤ max a b All goals completed! 🐙
example (a b : Int) : max a b = max b a := a:Intb:Int⊢ max a b = max b a All goals completed! 🐙
grind 获得传播器,用于评估 BitVec 对文字的操作,包括通过E 图中记录的等式 (#14393):
example {x : BitVec 64} (h : x = 0#64 + 42#64) :
BitVec.extractLsb' 63 32 x = 0#32 := x:BitVec 64h:x = 0#64 + 42#64⊢ BitVec.extractLsb' 63 32 x = 0#32 All goals completed! 🐙
它还收集了一批正确性修复:
-
未标准化成
grind所期望形式的位向量字面量可能被视为两个不同的值;其中一种情况甚至会生成被内核拒绝的证明(#14371 / #14370 / #14379); -
0 ∣ p形式的约束可能让搜索陷入循环(#14373); -
在不具备
NoNatZeroDivisors的环中,环求解器可能丢失信息(#14390); -
现在会检测并修复用户简化过程可能悄然破坏的
SymM项不变量(#14299)。
新的 liaSteps 选项限制了硬线性整数算术 (#14392) 的搜索。最后,仅当两个理论都已在 E 图中时,才重新调整容器操作的电子匹配注释以连接两个理论,而不是一个拖入另一个。更多信息请参见 #14177 / #14194 / #14192 / #14182 / #14178。
Float 不再不透明
Float 和 Float32 是没有逻辑内容的不透明类型。 #14079 添加了 Float.Model 和 Float32.Model,针对 Berkeley TestFloat 案例的本机实现进行了验证,#14091 重新定义了包装它们的类型,并将算术、比较和转换委托给模型。编译后的代码不受影响。这不是一个完整的浮点库 - 重点是让下游连接到 Float 以便传输其定理。
两个后果是显而易见的。 #14180 添加了一个 DecidableEq 实例来比较位模式,这不是 == 实现的 IEEE 754 关系。并且 #14110 重写了 Float.ofScientific ,以便它正确舍入 - 它通过了 parse-number-fxx-test-data 套件的五百万次测试,但代价是回退路径慢得多 - 现在在内核中减少了:
def nan : Float := 0.0 / 0.0
/-- info: false -/
#guard_msgs in
#eval nan == nan
example : nan = nan := ⊢ nan = nan All goals completed! 🐙
example : (0.0 : Float) ≠ -0.0 := ⊢ 0.0 ≠ -0.0 All goals completed! 🐙
example : 0.1 + 0.2 != 0.3 := rfl
该实例还支持浮点文字作为 match 模式 (#14181),因此 0.0 和 -0.0 选择不同的分支:
def describe (x : Float) : String :=
match x with
| 0.0 => "zero" | -0.0 => "negative zero" | _ => "other"
/-- info: "negative zero" -/
#guard_msgs in
#eval describe (-0.0)
Lake
#14235 使模块存档 (.ltar) 内容稳定:无论输入、检出路径或构建机器如何,字节相同的模块输出现在都会生成字节相同的存档,因此仅输入更改不会上传新字节,并且相同的输出会在缓存服务的各个修订版中进行重复数据删除。 #13646 添加了 requiresModuleSystem 包选项,当没有 module 标头的文件导入包时发出警告; allowNonModules 选择退出。
两个修复消除了一类 compiled configuration is invalid; run with '-R' to reconfigure 故障:#14284 使中断的配置留下有效跟踪,而 #14285 在根本无法读取跟踪时重新配置。还有用于依赖项和链接信息的新模块方面 (#14300 / #14254),以及带有 exe 模板的 lake new/lake init 不再发出库文件 (#14366)。
内核健全性修复和进一步改进
此版本修复了 Lean 内核中的错误并提高了其稳健性。一些健全性错误只能从同一进程中运行的恶意元程序中利用(已知这是不安全的)。其他的在导出格式中仍然存在并影响 也通过 comparator 进行校对,除非也使用像 nanoda 这样的外部检查器。
-
PR #14498 防止不透明值中的自由变量。健全性错误,但不影响
comparator的用户。 -
PR #14577 对嵌套归纳式的幻像参数的参数进行类型检查。健全性错误,影响
comparator的用户。 -
PR #14607 添加了更多针对自由变量的检查。可能存在健全性问题,不影响
comparator。 -
PR #14608 检查递归定义中的级别参数一致性。不是已知的健全性问题,因为它只影响标记为
partial或unsafe的声明。 -
PR #14609 修复了模块系统中的健全性问题。不影响
comparator的用户。 -
PR #14613 识别可以标准化为
Prop的级别表达式。健全性错误,影响comparator的用户。 -
PR #14615 为归纳处理添加了更多级别标准化。不是健全性错误。
-
PR #14616 拒绝在名称中使用
_nested的名称,以防止与内核的嵌套归纳式内部结构发生冲突。健全性错误,但不影响comparator的用户。 -
PR #14621 为嵌套归纳的处理添加了更多强化。
-
PR #14631 在比较投影表达式时检查投影表达式的名称字段。这会使内核变硬。
-
PR #14632 通过显式检查更多不变量来强化内核。
-
PR #14633 通过更快地检查本地上下文声明的类型来强化内核。
重大变更
透明度
#13895 默认启用 backward.isDefEq.respectTransparency.types:在可约化、实例或隐式透明度处分配的元变量现在将其类型与 隐式 处的值类型进行比较,而不是默认透明度,并且许多现有声明被标记为隐式可约化以进行补偿。回报是对所展开的事情有更多的控制,以及更好地扩展大型项目。
破坏的症状是 simp、grind 或其他策略停止应用的引理,因为参数的类型在定义上不等于隐式透明时的预期类型。
迁移:
-
set_option backward.isDefEq.respectTransparency.types false恢复旧行为。尽可能缩小范围。 -
持久修复是找出为什么引理语句或目标在隐式透明度下类型不正确并解决这个问题,或者标记涉及的定义
@[implicit_reducible]。 -
要进行诊断,请先找到
set_option linter.tacticCheckInstances true,然后找到trace.Meta.isDefEq、trace.Meta.isDefEq.printTransparency和trace.Meta.Tactic.simp。在旧工具链上运行simp?显示哪个引理“应该”触发。 -
对于其语句为
simp规范化的自动生成引理(在 Mathlib 中,来自@[simps]和@[reassoc]),修复通常属于生成引理的位置,而不是出现错误的位置。
相关地,#13637 将旧的 instances 透明度一分为二,得到 none < reducible < instances < implicit < default < all。 @[implicit_reducible] 不再带有 @[instance_reducible] 的副作用,例如让类型类搜索看透声明;为此使用 @[instance_reducible] 。 with_implicit 策略加入 with_reducible_and_instances。
其他重大变更
-
#13956 通过
maxRecDepth而不是物理堆栈来限制内核类型检查,从而使(kernel) deep recursion detected跨平台和构建具有确定性。深度递归代码可能需要set_option maxRecDepth碰撞。 -
#14372 将
Lean.initializing、enableInitializersExecution和isInitializerExecutionEnabled从IO移动到BaseIO。lean_enable_initializer_execution现在返回一个标量,因此 C FFI 调用者必须停止使用lean_io_result_*函数或lean_dec_ref处理其结果;无法适应可能会出现段错误。 -
#13679 阻止代码生成检查公共类型的私有构造函数。在极少数情况下,这会改变结构的 FFI 表示;该手册不再建议直接从 C 访问此类字段。
-
#14241 使
bv_decide使用ext_iff引理来实现结构相等,否则不对其进行推理,因此结构可能需要@[ext]或手写的外延性引理。 -
#14091 将
Float.lt和Float.le从Float → Float → Prop更改为Float → Float → Bool;LE和LT实例不受影响。 -
#14290 将
int_toBitVec拆分为SymM和MetaM简化集;simp调用现在应使用int_toBitVec_meta。 -
#14206 将 Lake 的延迟文档字符串检查移动到
linter.doc.deferred选项下的检查器框架上;自定义 Verso 文档字符串元素成为双构造函数类型。 -
一轮命名空间和模块卫生重定位位于错误位置的声明 -
Int.Linear到Int.Internal.Linear(#14255),IO.AsyncList到Lean.AsyncList(#14263),以及 #14265 / #14260 / #14258 / 中的更多内容#14256 / #14303 / #14302 / #14293。Nat.ne_of_gt现在是protected(#14216)。 -
Lake 的
setup方面不再可从命令行界面构建,因为它生成 JSON 而不是工件 (#14300)。
语言
-
#14498 修复内核不健全性:就像定义和定理一样,
opaque声明的值不得包含 fvar。 -
#14352 提供实验性
postprocess_traces tracePostprocessor in cmd命令,该命令对于处理大型跟踪节点树非常有用。它运行命令cmd,然后使用函数tracePostprocessor转换迹线。转换可以影响默认展开或折叠哪些节点,可以更改跟踪节点的消息,还可以添加或删除节点。 示例: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 向
Syntax.structEq添加适当的借用注释。它们是必需的,因为它处于引导过程的早期,它通过Substring的引导包装器进行路由而无需借用注释。它们是相关的,因为Syntax.structEq最终会从alphaEq传递调用。 -
#14196 改进了有关可还原性属性的警告和错误。部分解决#13351。
-
#14361 通过尝试跳过用于传播宇宙约束的
check调用来优化applyAbstractResult?。优化非常简单:它检查结果是否包含任何可以分配的元变量。 -
#14333 当弃用有利于自身的声明时,会导致
@[deprecated]属性错误。 -
#14325 添加一个检查器,对
open语句发出警告,这些语句实际上不会打开以给定名称结尾的所有命名空间。 -
#14335 当非单子定义使用嵌套递归调用(例如
f (f x))时,使partial_fixpoint报告有用的单调性错误,而不是令人困惑的Unknown constant错误,这要求函数是尾递归的。 -
#14330 使
tryResolve在成功统一目标类型与候选实例类型后直接分配目标元变量,而不是使用isDefEq重新检查类型。对于无元变量的目标来说,重新检查是多余的,而且成本可能很高。 -
#14259 向
unusedVariables检查器添加提示,建议使用下划线重命名未引用的名称。 -
#14153 为
NameMap和NameSet添加Insert实例。 -
#13956 通过使用现有的
maxRecDepth选项而不是物理堆栈大小来限制内核类型检查,使内核的(kernel) deep recursion detected错误具有确定性。以前的限制取决于本机堆栈,因此它会因平台、构建和优化级别而异,并且无法可靠地重现;它现在是maxRecDepth单独的函数,并通过set_option maxRecDepth <num>以通常的方式引发。 -
#14297 使
do块的match (dependent := true)分支内的裸return以依赖精化后的分支类型为目标,因此像| 0 => return 0这样的分支会针对精化后的do块结果类型进行类型检查,而无需将其包装在嵌套的(do …)中。 -
#13895 默认情况下启用
backward.isDefEq.respectTransparency.types选项。当以可简化、实例或隐式透明度分配元变量时,这意味着元变量及其分配值的类型以隐式、先前默认的透明度进行比较。它还使许多现有的声明可以隐式简化。这一变化增强了用户对正在展开的内容的控制,从而提高了大型项目的可扩展性。 -
#14249 扩展
dupNamespace检查器以允许用户选择通过linter.extra.dupNamespace.consecutiveOnly选项来检查命名空间组件的非连续重复使用。默认情况下,仅检查连续的。选择非连续检查与 mathlib4#39793 中引入的行为相匹配。 -
#14247 修复了当文档字符串附加到
coinductive谓词并且启用doc.verso时出现的错误(“无法解释绑定器”)。 -
#14234 修复了自动完成功能(以及其他 InfoTree 驱动的使用者,例如交互式术语目标和悬停弹出窗口),以在光标位于术语级别
open ... in <term>或set_option ... in <term>范围下时查看增强的openDecls和options。此前,两位精译器仅通过withTheReader/withOptions更新了运行时Core.Context,但没有将相应的PartialContextInfo.commandCtx节点推送到 InfoTree 中;因此,消费者会看到外部命令的openDecls/options,并且,例如,即使在匹配的open下也提供完全限定的名称,或者忽略本地set_option pp.fullNames true渲染漂亮的目标。 -
#14214 恢复leanprover/lean4#14193。它所引起的基准测试问题几乎肯定不是由它引起的,而是噪音;与用户更复杂的心智模型的负面影响相比,实际收益是微不足道的。
-
#14200 导致宏中的文档字符串遵循宏定义站点(而不是其使用站点)的
doc.verso选项的值。之前,使用了 use-site 选项,因此无法在选项值不一致的上下文中使用宏,因为解析的格式不正确。现在,无论选项的本地设置如何,都会使用语法中的解析格式。 -
#14198 修复了以下错误:在存在
_参数的情况下以及在宏生成的声明中,对于不带括号的绑定器,按名称引用参数失败。 -
#14191 修复了 Verso 内容中有效块打开位置中的行开头的转义内容被跳过的问题,就好像它是空格一样。
-
#14193 将传播到解析器的选项限制为以
doc.verso开头的选项,以提高性能超过 #14189。 -
#14189 将命令、术语和策略中使用的 set_option ... 形式的选项值传播到正文的解析中。这意味着可以更方便地启用或禁用 Verso 语法,并使
set_option ... in ...在语义上与open ... in ...保持一致。 -
#14115 添加了对 Verso 文档字符串的可扩展 Markdown 渲染的支持。
-
#14181 让
match使用Float和Float32文字作为模式,就像String、UInt64和其他文字类型一样。编译器使用类型的DecidableEq实例(位模式相等)将审查者与每个文字进行比较,因此例如0.0和-0.0是不同的模式。支持负文字,例如-1.5。 -
#14114 更改了霍尔三重表示法,因此
;将异常后置条件引入为单个EPred项,而不是包装在epost⟨…⟩中的异常情况列表。这让符号表示epost变量或任何EPred,并使epost⟨…⟩成为在该槽中编写的普通显式构造函数。 -
#13637 将
TransparencyMode.instances和ReducibilityStatus.implicitReducible拆分为两个透明度级别,以便@[implicit_reducible]注释不再具有@[instance_reducible]的副作用,例如允许类型类搜索查看标记的声明。 -
#14120 修复了面向语言服务器的接口,例如
findDocString?,它从模块系统下的.olean.server获取其信息,如果相关模块是使用all导入的,则也可以在命令行上工作。 -
#14112 添加
wait_for_expected_type%术语精译器,它详细精译了针对预期类型的参数,但当该类型是未分配的元变量时会推迟。这使得符号可以推迟断言,直到通过实例综合解析outParam为止,因此裸露的 λ 检查折叠载体,而不是将其展开为点状函数格。
库
-
#14303 从相应的命名空间中删除内置简化过程用于基本类型的帮助器定义。
-
#14302 将关于
ExceptT的三个公共引理从Std.Internal.Do.WP.Lemmas(内部模块)移至Init.Control.Lawful.Instances,其中其余ExceptT引理所在。 -
#14293 将公共声明
Function.Injective.leftInverse从Init.Grind移出并移入Init.Data.Function。 -
#14255 将
Int.Linear重命名为Int.Internal.Linear,以更清楚地表明这些是omega/grind/simp +arith的内部实现细节,用户不应直接依赖。 -
#14265 将污染公共命名空间的各种声明移至内部命名空间(如
Lean)。 -
#14269 使 Windows 转换时间在转换秒数时使用 ceil,这可以避免丢弃小数秒并导致相差一行为。
-
#14231 将
Array.back、Array.back!和Array.back?标记为@[expose],以便在下游模块中它们的主体可用于定义缩减。以前decide无法评估来自另一个模块的#[1, 2, 3].back? = some 3等目标,即使这些函数定义的getElem?/size访问器已经公开。 -
#14267 通过标记其内部
loopsemireducible(默认情况下有根据的定义是irreducible)并公开foldl,使Fin.foldl在内核中减少,因此内核对Nat上有根据的递归的特殊支持适用。之前Fin.foldl被困在decide/#reduce/Decidable下,与已经减少的Fin.foldr不同:example : Fin.foldl 8 (fun a i => a + i.val) 0 = 28 := by decide -- now succeeds
-
#13804 在 TzIf V2 和 V3 页脚中添加 Posix TZ 字符串(生成
RecurringRule类型)的解析,以便在时间戳未被ZoneRules中的转换数组覆盖的情况下,lean 可以生成时区转换。 -
#14263 将
IO.AsyncList重命名为Lean.AsyncList以避免污染公共IO命名空间。 -
#14260 将
Lean.Data.Lsp.Communication中污染全局IO.FS.Stream命名空间的一些声明移至内部命名空间。 -
#14258 将
Lean.Data.Lsp.Utf16中的声明从Char移动到Char.Internal,从String移动到String.Internal,以便String命名空间在此实现模块中不会被污染。 -
#14256 将
LLVM命名空间重命名为Lean.LLVM以减少对全局命名空间的污染。 -
#14252 通过使用廉价的随机源而不是每次调用
getRandomBytes来加速Selectable.one、Selectable.combine和Selectable.tryOne。 -
#14244 将
Quot文档中的“可以看到”替换为“可以看到”,并重新包装该段落以适合 100 列,而不拆分短片段。 -
#14212 添加
List.Nodup.length_le_of_subset:作为另一个列表的子集的无重复列表不长于该列表。目前仅在电池中可用(通过Subperm接口);这里直接用归纳法证明。 -
#14211 添加
List.perm_ext_iff_of_nodup:两个无重复列表当且仅当它们具有相同的元素时才是彼此的排列。目前仅在电池中可用(通过Subperm证明);这里直接从perm_iff_count证明。 -
#14210 在
List.idxOf和索引之间添加往返引理:List.getElem_idxOf(xs[xs.idxOf x] = x,当x出现在xs中时)和List.Nodup.idxOf_getElem(idxOf xs[i] xs = i对于无重复的xs)。这些目前仅适用于电池。 -
#14216 将
Nat.ne_of_gt标记为protected,以便必须通过其完全限定名称来引用它,与周围的Nat顺序引理一致。命名空间内引用相应地更新为限定名称。 -
#14209 添加
List.pairwise_lt_finRange、List.pairwise_le_finRange和List.nodup_finRange,说明List.finRange n严格递增、递增且无重复。这些是有关finRange的基本事实,目前仅适用于电池。 -
#14177 降低
List.count和Array.count电子匹配的攻击性。以前,任何对 count 的调用都会直接触发有关过滤器的理论。但是,鉴于count有自己的一组grind注释,我们认为count应该仅在 E 图中已可以调用filter时才开始与filter连接。这样我们就不会不必要地从count触发filter理论。 -
#14194 通过不再每次有机会自动转换为
drop/take,降低了eraseIdx电子匹配的攻击性。 -
#14192 降低了电子匹配注释的侵略性,以根据容器的大小来限制上述
count操作的结果。现在,只有当大小和计数操作都已在 E 图中时才会触发它们。与 find 的注释工作方式类似。 -
#14190 添加了
Std.Internal.Do验证框架使用的两个小型独立的Lean.Order.CompleteLattice基础设施。 -
#14182 只要
findIdx可用,就会停止通过电子匹配自动将findIdx连接到findIdx?,而仅在findIdx和findIdx?可用时才这样做。 -
#13799 修复了
aligned类型和名称顺序,因此Week.Ordinal.OfMonth现在是Week.OfMonth.Ordinal并且我们有Week.OfMonth.Aligned.Ordinal这是一个非常大的类型,但它表明我们可以有 1 到 5 对齐的周。 -
#14180 实现一个
DecidableEq Float实例,它检查底层位模式的相等性。 -
#14178 教导grind这样一个事实:一旦
count a xs和a ∈ xs出现在 E 图中,使用count a xs = 0 ↔ a ∉ xs可能会很有趣。 -
#14116 使用
Selectable.combine修复了死锁,还修复了Selectable.one中递归互斥锁的一个简单问题。此 PR 修复了 #14090 -
#14174 更新
Std.Time.GenericFormat.parse和Std.Time.GenericFormat.parse!的文档字符串,说明它们解析为DateTime,匹配它们的返回类型。 -
#14110 完全重写了
Float.ofScientific的实现。 -
#14091 更改
Float和Float32类型的定义以包装 #14079 中引入的Float.Model类型。 -
#14079 添加类型
Float.Model和Float32.Model,它们将用作Float和Float32类型的逻辑模型。 -
#14034 将霍尔三重引理
Triple.observe添加到Std.Do中。它从无状态程序obs的规范中证明了prog的三元组:观察obs的后置条件Q(通过h)并使用Q建立wp⟦prog⟧ Post(通过hgoal)产生⦃Pre⦄ prog ⦃Post⦄。前提hp要求obs是无状态的:它的成功运行使状态保持不变,这适用于无状态单子的每个程序,例如Except。 -
#14067 添加最弱前提条件规范引理
Spec.monadLift_Id,以便mvcgen/mvcgen'可以释放将Id值提升到Pure/WPMonad变压器堆栈中的 do-bind(例如StateT Nat Id内的let x ← (pure 5 : Id Nat))。 -
#14078 修复了
IntX.ofIntClamp系列函数中的错误。
策略
-
#14618 修复了
grind在处理量词下以#语法书写的位向量字面量时的回归,例如example (f g : Nat → BitVec 2) (h : ∀ n, f n = g n ||| 1#2) : f 0 = g 0 ||| 1#2 := by grind。此前该策略会触发内核错误,而不是关闭目标。 -
#14393 实现
grind传播器,用于评估文字上的BitVec操作 -
#14392 向
grind添加了新的liaSteps配置选项。其动机是快速中断对硬线性整数算术问题的搜索。 -
#14390 修复了
grind环解算器中的问题。当环R不满足[NoNatZeroDivisors R]时,多项式简化可能会丢失信息,影响完整性。 -
#14195 使用自动帧推断扩展
vcgen:@[frameproc]属性允许程序类型注册它如何构建资源,然后vcgen在调用中携带该资源,而无需用户指定显式frames子句。成帧不再与晶格相遇相关,而是适用于任何保留连接的帧运算符,因此成本预算、分离逻辑足迹和跟踪不变量通过相同的机制进行帧处理。 -
#14379 修复了
grind规范化器中的引导问题。 在我们处理Init/Data/BitVec/Lemmas.lean之前,必须将BitVec.ofNatLT归一化定理添加到grind归一化集中。否则,模式不会正确标准化。 -
#14373 修复了
grind中由0 ∣ p形式的约束触发的非终止问题。 -
#14371 修复了
grind中由非标准化位向量文字引起的两个错误。BitVec.ofNatLT文字和超出范围的OfNat.ofNat文字(例如(17 : BitVec 4))不会简化为grind使用的OfNat.ofNat正常形式,因此同一值的两个表示形式被视为不同的值,并且grind产生被内核拒绝的无效证明:example (x : BitVec 4) (_h1 : x = BitVec.ofNatLT 1 (by decide)) (_h2 : x = 1#4) : True := by grind -- kernel error before this PR
-
#14370 修复了
bitVecOfNat := false时BitVec简化过程中的错误。这个错误 影响grind,因为它使用bitVecOfNat := false。这是 Henrik 报告的一个例子 这暴露了问题。 -
#14358 为
grind的内部信封类型Ring.OfSemiring.Q type实现快速路径。 -
#14346 优化辅助
grind类型IntModule.OfNatModule.Q的grind相关实例的构造。这是 Mathlib 的一个主要瓶颈。 -
#14314 确保
shareCommon内部缓存在repairAndShare处重用。 -
#14299 使
shareCommon保持grind和Sym.simp使用的SymM表示不变量:可约常量被急切地展开,并且内核投影被折叠到投影函数应用程序中。这些不变量以前仅由grind预处理器建立,并且很容易从用户简化过程和内部代码路径中违反(例如,Sym.inferType从从未预处理的环境签名返回类型),从而产生静默 E 匹配和索引失败。现在,当术语进入最大共享术语表时会检测到违规行为并自动修复。 -
#14295 让
vcgen处理包装在mdata节点中的程序,例如规范精译留下的save_info注释,而不是因内部错误而失败。 -
#14290 通过将
int_toBitVecSymM 拆分为 SymM 和 MetaM simp 集来使其兼容。int_toBitVec的现有用户现在应该在其simp调用中使用int_toBitVec_meta。 -
#14289 确保
finish?在需要时将intros和by_contra添加到生成的策略脚本中作为预处理步骤。 -
#14287 为
sym =>模式实现rw策略。 它还将Lean/Elab/Tatic/Grind/Sym.lean分解为更小的文件。 -
#14137 向
Sym模式匹配器添加指针相等快速路径:当模式子项指针等于目标时,它是一个等于目标的封闭项,没有要绑定的变量,因此匹配立即成功,无需遍历子项。 -
#14281 确保方程定理的右侧在预处理期间不会减少 ζ。此问题影响 vcgen(请参阅 @sgraf812 的新测试)。
-
#14280 修复了
sym => apply <rule>可以使用包含松散实例元变量的证明项来关闭目标的错误。 -
#14279 在
SymM中向类似intro的函数添加了新的hygienic参数。 -
#14278 在
sym =>模式下实现case => ..策略。它与vcgen相关(请参阅新测试)。新功能尝试在常规策略模式下模拟case => ..策略。 -
#14277 修复了
SymM中虚假的apply故障。 -
#14241 改变了
bv_decide处理结构的方式。以前bv_decide中对结构相等的支持是有限的。现在它将使用ext_iff引理(如果可用),否则不会推理结构的相等性。这一变化应该会增加bv_decide对结构的推理能力。然而,这是一个重大更改,可能需要用户使用@[ext]注释以前存在的结构,或者以其他方式为它们定义和标记外延引理。 -
#14227 重构
bv_decide处理USize和ISize的方式。这对于bv_decide中的SymM支持是必需的,因为在SymM中调用revert是非法的。 -
#13830 在常见的证明站点添加自动
try?建议,由三个选项控制 默认关闭:-
autoTry.onEmptyProof— 建议空证明和空子证明:空by, 空·、空case h =>等等。 -
autoTry.onUnsolvedGoal— 与autoTry.onEmptyProof类似,但也会在校样上触发 子证明已经包含一些策略并且留下了未解决的目标。建议 附加到现有序列(例如by skip→by skip; <found>)。 -
autoTry.onSorry— 建议sorry策略;该建议替换sorry。
-
-
#14205 使
impossible策略组合器不再在否定目标前运行cleanup,因为那会违背该组合器的用途。 -
#13712 使
exact?、apply?、rw?和grind +locals不再等待先前的异步 定理体位于同一文件中,以在迭代当前模块时完成内核检查 声明。之前,这些策略走env.constants.map₂,这迫使env.checked和 因此会阻塞每个待处理的异步分支;在编辑器会话中,这表现为try?和exact?似乎挂在长文件的顶部附近。 -
#14167 在
vcgen策略中添加一个frames子句,该策略将状态断言(框架)附加到匹配的程序,因此有关程序的状态的事实保持不变,即使在注册规范删除它们的调用中仍然存在。 -
#14146 将实验性的基于 Sym 的
mvcgen'策略重命名为vcgen,包括其 grind 模式步骤、with放电子句和simplifying_assumptions/until/invariants语法。原来的mvcgen策略没有改变。 -
#14142 通过在第一次查找时将每个匹配的规范模式内部化到
SymM共享表中来加速mvcgen'规范查找,因此其实例参数变得与程序的指针相等,并且不需要在以后的每次查找时重新内部化。 -
#14138 修复了
mvcegn' ... with <tac>的错误消息。这样做的主要动机是,当我们编写mvcgen' with grind时,用户看到的错误消息是unexpected identifier; expected grind,这非常令人困惑。发生这种情况是因为我们排除了grind序列,其语法类别称为grind。 我正在为消解器策略定义一个单独的语法类别,称为mvcgenWith,如果它是一种策略,则抛出更有意义的异常。 -
#14134 当规则被缓存时,通过将每个向后规则的模式内部化到
SymM共享表中一次,而不是在每次匹配时重新内部化其实例参数,来加速mvcgen'匹配。 -
#14080 从
WPMonad中提取WP类型类,以便最弱前置条件推理和mvcgen'适用于任何程序类型,而不仅仅是单子。这可以验证深度嵌入的语言:具有WP实例但没有WPMonad实例的程序类型(例如具有自己的操作语义的归纳命令语法)现在可以使用Triple指定并由mvcgen'分解。 -
#14119 修复了
mvcgen/mvcgen'无法分割判别式望远镜相关的match,即当后面的判别式的类型提到了前面的判别式时(例如match n, h with,其中h : 0 < n)。抽象这样的匹配器之前会产生类型错误的预分割动机。 -
#14107
Nat.min_def、Nat.max_def、Int.min_def和Int.max_def带有@[lia]属性,因此lia策略通过电子匹配实例化它们,并且可以开箱即用地证明涉及min/max的目标。这解决了最常见的情况,其中omega以前可以被lia替换,但lia无法看到min/max定义,需要回退到完整的grind策略。 -
#14098 添加了一个内置的
@[lia]属性,该属性为lia策略提供了一个小的 E 匹配引理集。以前,lia(仅限cutsat的grind配置)在禁用 E 匹配的情况下运行,因此无法看到定义引理,例如Nat.max_def。现在lia仅实例化标记为@[lia]的引理,而禁用更大的@[grind]集。 -
#14102 将名称
WhileInvariant从Std/Internal/SpecLemmas更改为RepeatInvariant,因为在大多数情况下,在验证forIn-repeat 循环时会调用它。此外,我们添加了一个新的缩写来构造RepeatInvarinats。该缩写指定了一个条件inv,它应该在每个循环迭代(甚至是中断循环)的末尾保持,以及一个条件onDone,除了inv* 之外,它还应该在循环结束时保持。 在正常的while循环的情况下,后一个总是可以被视为循环条件的否定。 -
#14099 在
mvcgen'中添加⊤规范化。 在mvcgen运行期间,特别是在引入额外的状态参数时,⊤可能会变成⊤ s₁ s₂ ⋯ sₙ。 我正在添加一个过程,它可以动态构建⊤ s₁ s₂ ⋯ sₙ = ⊤的证明并替换它。 -
#14095 当蕴含的断言格是诸如
(a : α) → β a → Prop之类的依赖函数类型时,使mvcgen'报告明确的错误,而不是循环直到心跳耗尽。阶数是普通的逐点函数阶数;限制是mvcgen'的剥离规则Lean.Order.le_of_forall_le当前无法应用于从属函数晶格。 -
#14081 统一
mvcgen'如何将@[spec]注释转换为后向规则,使注释的优先级对方程规范生效,并拒绝既不是霍尔三元组、方程也不是要展开的定义的@[spec]注释。 -
#14089 让
mvcgen和mvcgen'应用@[spec]定理,其陈述是包装霍尔三元组的可简化缩写,例如abbrev foo.spec := ⦃P⦄ foo ⦃Q⦄。以前,程序一直卡住,因为规范虽然已注册,但在查找时被丢弃。 -
#14015 将实验性的
mvcgen'策略移植到新的Std.Internal.Do元理论中,其中验证条件生成基于晶格蕴涵pre ⊑ wp x post epost。在证明表面上可以看到两个变化:mvcgen'现在急切地将所有状态组件引入为局部假设,因此更多事实到达grind;循环不变量不再需要重述异常后置条件。
编译器
-
#14372 将
Lean.initializing、enableInitializersExecution和isInitializerExecutionEnabled从IO移动到BaseIO。 -
#14365 确保
unsafe项得到正确内联。以前,一些不安全术语t作为unsafe t内联出现,会创建一个单独的辅助声明,该声明可能最终不会被内联。 -
#14343 修复了新的 1GB 堆栈大小未用于主
lean线程本身的问题,例如用于序列化或--run。 -
#14139 再次在发布模式下禁用 libleanshared.so 的符号剥离。事实证明,
--strip-unneeded不仅会删除我们不关心的符号。 -
#14272 更改
dbgTraceIfShared以借用其消息(s : @& String),并在运行时和标头中进行匹配的b_obj_arg/b_lean_obj_arg调整。 C 实现只读取字符串并且从不使用它,因此每次调用时所拥有的参数都会泄漏;这种泄漏在典型使用中不会被注意到,因为字符串文字被编译为持久常量,这些常量不受引用计数的影响。动态构造的消息每次调用都会泄漏一次。借用与实现实际执行的操作相匹配,并且使调用者无需进行引用计数操作。在审核 #14271 中修复的模式的运行时时发现的。 -
#13679 修复了使用具有当前范围内无法访问的私有字段和类型的结构时代码生成中断的问题。
-
#14127 通过使其原子化,修复了
lean_task_imp.m_canceled上理论上但非实际的竞争条件。 -
#14108 将
lean_task的m_imp字段更改为原子。这是必要的,因为在get_task_state_core中,我们访问m_imp以查看任务是否在获取互斥体之前完成。因此当前完成的存储器访问是UB。
外部函数接口
-
#14184 为需要模拟来自 C FFI 的多个
withImporting调用的 Lean 用户导出lean_set_initializing符号。
文档
-
#14222 将许多似乎明确打算作为文档字符串的注释转换为文档字符串,避免那些已在 #13006 中转换的注释。
服务器
Lake
-
#14366 修复了
lake new和lake init,使其不在exe模板上发出库文件。它还修复了一个相关的错误,其中命令有时可能会覆盖现有包的库文件。 -
#14300 添加了
presetup、depTrace和depHash方面,它们提供了模块完整依赖项集的不同视图。此外,setup方面不再可在命令行界面上构建(因为它生成 JSON 而不是工件),现在包含全套传递性导入工件,修复了lake lean的setup.json中缺少的问题。 -
#14364 将
getLakeSharedDynlib添加到 Lake 接口。这是一个简单的一元便利函数,可以检索检测到的 Lake 安装的LakeInstall.sharedDynlib。 -
#14285 使 Lake 在无法读取配置跟踪时重新配置,而不是使用
error: compiled configuration is invalid; run with '-R' to reconfigure中止。importConfigFile已经针对陈旧、错误的工具链或部分格式错误的跟踪自动重新配置;无法解析的跟踪并不比丢失的跟踪提供更多信息,因此现在以相同的方式处理它 - 路由到相同的elabConfig (← acquireTrace h) …路径 - 自行恢复,而不需要手动-R。当跟踪没有可用的options字段时,它会回退到cfg.lakeOpts,与不存在跟踪时 fresh-configure 分支使用的选项值相同。 -
#14284 使中断的 Lake 配置可恢复。
importConfigFile将编译配置跟踪写入缓冲句柄,然后调用IO.FS.Handle.truncate— 它设置文件大小,但不会刷新缓冲写入,如其自己的文档字符串注释 — 在可能缓慢的配置精译之前。在该窗口中终止的lake进程(中断或取消的构建)在磁盘上留下跟踪作为 NUL 字节大小的占位符,没有.olean,因此以后的调用会失败并显示error: compiled configuration is invalid; run with '-R' to reconfigure。在截断和细化之前刷新完整的跟踪意味着中断会留下有效的跟踪,并且不会留下.olean,Lake 现有的最新检查已将其视为自动重新配置的触发器。 -
#14254 添加了两个新的模块方面:
linkInfoExport和linkInfoNoExport。它们提供有关如何链接模块的信息。它还为buildSharedLib、buildLeanSharedLib和buildLeanExe提供了Sync变体,这些变体在Job内部而不是跨它们工作。 -
#14235 使 Lake 的模块存档 (
.ltar) 内容稳定:字节相同的模块输出现在会生成字节相同的存档,无论输入、检出路径或构建它们的机器如何,因此仅输入更改(例如导入模块中的注释编辑)不会上传新的存档字节,并且相同的输出会在缓存服务上的修订版中进行重复数据删除。 -
#14206 调整延迟文档字符串检查机制以使用检查器机制,提供类似于环境检查器的界面。这用已使用的界面替换了自定义 CI 设置。延期检查由选项
linter.doc.deferred控制。 -
#14240 确保可执行文件在从 Lake 缓存恢复时可执行,即使它们最初在缓存中不可执行(例如,因为它们是通过
lake cache get下载的)。 -
#14219 添加了用于检索完整的核心动态库集的接口。目前来说,这些是
libleanshared、libleanshared_1和libleanshared_2。和libInit_shared。这些库在 Windows 和 Unix 上具有不同的相互依赖性,因此它们使用Dynlib进行建模,以便跟踪此信息。 -
#14220 添加
Dynlib.runtimeOnlyDeps。它指定不应链接的传递依赖项,但需要在预编译时预加载以进行lean精译(例如,在运行时通过dlopen动态加载的库)。 -
#14156 允许不依赖于任何动态库的模块在
true之间切换platformIndependent并取消设置而无需重建。 -
#14130 修复了
Package.remoteUrl?,因此空的remoteUrl返回none,非空的remoteUrl返回some remoteUrl。 -
#13646 添加了新的 Lake 软件包选项
requiresModuleSystem。当包将其设置为true时,每当非模块系统文件(没有module标头的文件)导入包的模块时,Lake 都会发出警告,无论是从下游消费者还是从包本身内的非模块文件。这表明包的接口需要模块系统的可见性和详细语义。配套选项allowNonModules允许导入包选择退出这些警告,声明它故意将非模块系统文件与模块系统依赖项混合在一起。
其他
-
#14633 在将相应的声明添加到本地上下文之前,使
infer_lambda和infer_let检查绑定器的类型,并检查let的值,这是infer_pi已经做的事情。没有有效的声明会改变行为。 -
#14632 是对内核的强化。这些提交都没有修复普通Lean代码可到达的错误:每个提交都采用内核已经依赖的不变量并在本地检查它,而不是假设它在其他地方保存。其目的是让内核相邻部分中的未来错误表现为一个干净的错误,而不是被放大。
-
#14631 使内核在确定两个投影表达式定义上是否相等时比较结构名称。
type_checker::is_def_eq_core和equiv_manager::is_equiv_core都只比较投影索引和投影表达式,忽略proj_sname。 -
#14621 使内核在消除嵌套归纳类型后重新检查它添加到环境中的声明。
-
#14616 修复了一个内核错误:归纳声明可以引用内核在消除嵌套归纳时生成的辅助类型之一,并最终得到类型错误的存储构造函数类型。这样的声明只能通过元编程来生成。
-
#14615 使归纳检查器测试结果宇宙是否为零直至归一化,以便
Sort (imax 1 0)和Sort 0描述相同的归纳类型。这两种拼写之前在构造函数字段是否可以携带数据、递归器是否仅消除到Prop以及该类型是否是类似 K 的归约目标方面存在分歧。只有使用元编程生成的声明才会受到影响,因为精译器在内核看到它们之前将级别标准化。 -
#14613 修复了一个内核错误:仅在宇宙归一化后排序为
Prop的类型(例如Sort (imax 1 0))不会被识别为命题,因此内核允许从证明中投影出非证明字段。这样的声明不能用表面语法编写,只能通过元编程生成,而nanoda拒绝它。 -
#14609 修复了模块系统中的健全性错误。
partial定义在跨越模块边界时会丢失其partial标记,因此下游模块可以从安全声明中使用它。这个问题只能通过元编程来利用。 -
#14608 检查相互块中的声明是否使用相同的宇宙参数。精译器已经强制执行了这个不变量,但是元编程可以绕过它。
-
#14607 向内核归纳类型模块添加缺失的
check_no_metavar_no_fvar检查。如果没有它,用户可以使用元编程来潜入包含自由变量或元变量的嵌套归纳声明。请注意,Comparator 会捕获此漏洞,因为 Lean4export 拒绝导出包含自由变量或元变量的声明。 -
#14577 修复了一个内核错误,其中参数参数类型错误的嵌套归纳数据类型可以被接受。
-
#14354 在
withExporting/withoutExporting处实现了较小的优化。当他们调用modifyEnv来切换Environment.isExporting时,MonadEnvMetaM的modifyEnv会擦除所有Core和Meta缓存。 -
#14131 修复了
finishCommentBlock,这样当-后面没有/时,它不会跳过它。