Gleam 如何判断一个 case 是否穷尽
来源:oyster.pckt.blog — 2026-10-10
📋 概述
这是一篇带读者走进 Gleam 编译器内部的长文,主题是 compiler-core/src/exhaustiveness.rs 的工作:在编译期判断 case 表达式的每个模式是否覆盖了主语所有可能取值,反过来也判断某个分支是否永远不会被命中。作者从 1984 至 1985 年 Lennart Augustsson 的《Compiling Pattern Matching》讲起,指出其框架是后续工作的基础——把 case 的子句按首要构造子分组,为子部分引入新变量,然后递归。Gleam 的实现在此之上做了拆解:Augustsson 的跳转同时承担了「继续在嵌套里匹配」和「失败」两件事,而 Gleam 把它们分成 Switch 与 Decision::Fail 两种类型。这样,若树建好后能在编译期发现 Fail,就证明原 case 不穷尽;再借助 missing_patterns.rs 沿树回溯,定位到那个永远无法匹配的具体情形并回报给用户,也就是 Maranget 2007 年论文里称作「witness(反例)」的东西。作者赞叹 Gleam 能直接告诉你「缺失的模式是:False」这类精确提示,是一种出色的用户体验。
🔑 核心要点
- 文件职责明确:编译期判断 case 是否覆盖全部取值,同时识别永远不会被命中的分支
- 理论源头是 Augustsson 1984–1985 年的《Compiling Pattern Matching》:按首要构造子分组、引入新变量、递归
- Gleam 的关键改良是把「继续在嵌套中匹配」与「失败」拆成 Switch 与 Decision::Fail 两种类型
- 由此得到的判据很干净:树建好后若在编译期发现 Fail,就证明原 case 不穷尽
- 定位缺失分支靠 missing_patterns.rs 沿树回溯,找出那个永远无法匹配的具体情形(witness,Maranget 2007 年论文中的反例)
- 用户体验是重点:编译器会直接给出「缺失的模式是:False」这类精确提示,而不是笼统的 non-exhaustive match 警告
💡 金句
「缺失的模式是:False」,它礼貌地这样告诉我。给出这样的信息绝非易事,这正体现了 Gleam 对用户友好的坚持。
👍 0
👎 0
← 返回 Lobsters 首页