从"更安全"到"确实正确"

Rust 常被当作 "更安全的 C",但亚马逊的研究人员在介绍 Verus 时先纠正了一个前提:更安全,不等于正确。数组越界在 Rust 里会让程序停下,这当然比内存被踩掉好;可一个正确的程序根本不应该发生越界。测试能覆盖几个样例,覆盖不了全部输入——比如目标值恰好是数组的最后一个元素,或者压根不在数组里。

佩戴防护镜、专注观察检测对象的工作人员

Verus 做的事:用数学规格检查全部输入

Verus 是一个开源的 Rust 自动化程序验证器。开发者先写下描述代码行为的数学规格,工具再机械地检查代码在所有可能输入下是否符合这份规格。规格与证明直接写在 Rust 源码里,语法接近 Rust 本身,普通编译器会忽略这些注解,所以带证明的代码依然能被常规项目依赖。求解器通常在一秒内给出反馈,快到可以在编辑器里显示红波浪线,让证明变成一种可以边写边改的日常动作。

它补的是 Rust 剩下的两块短板

为了性能,Rust 允许写 unsafe 代码,此时类型系统不再兜底,全靠开发者自己保证;而并发代码里 "锁保护的数据始终满足某个不变量" 这类性质,类型系统也说不清楚。Verus 让这两处都能做数学证明:unsafe 块可以重新获得机器检查过的保证;锁可以带上不变量——谁拿到锁,就必须拿到满足不变量的值,释放时还要证明性质依然成立。

成本与边界,值得说清楚

形式化验证不是银弹。Verus 的结论建立在几层假设之上:工具自身的正确性、开发者写的顶层规格是否符合真实意图、对运行时和标准库所做的假设,以及整条编译链是否可靠。规格写错,证明再漂亮也是白费——只是把错误从实现层挪到了规格层。这也是它目前主要出现在证书校验库、二进制格式解析、微内核、内存管理系统这类位置的原因:在那里,出错的代价远高于写证明的代价。

对普通团队的意义

对绝大多数业务系统来说,完整的数学证明仍然太重。但有一个习惯可以从今天开始:动手写代码之前,先把 "这段代码必须满足什么" 写清楚,哪怕只是几行注释里的不变量。规格是验证的前提,也是评审、测试和代码审查的共同语言。