像这样的表达式结果为 nil,但应该失败编译
(let (link: ) do)
像这样的表达式结果为 nil,但应该产生一个值
(let (link: do 1) do)
这对于所有具有“隐式 do”的特殊形式都适用:try/catch/finally,letfn/let,以及 fn/reify/deftype 例程。
这些特殊形式的“隐式 do”实现方式是相关解析器会明确地将其主体表达式委托给 BodyExpr.Parser。例如,
(let (link: x 1) (println x) x)
调用 BodyExpr.Parser.parse() 并传入列表 '((println x) x)。然而,BodyExpr.Parser 还被用于解析如同 '(do (println x) x) 的列表,在其他上下文中。为了处理这两种情况,其 parse() 方法会跳过其第一个形式,如果该形式是 'do 符号。因此,如果一个具有“隐式 do”的特殊形式的第一个表达式是裸的 'do 符号,那么该符号会被错误地丢弃。
附加的补丁通过在每个这种特殊形式实际插入一个显式的 'do 来修复此问题,这样 BodyExpr.Parser 就可以无条件地假设它的第一个形式是 'do,并跳过它。现在 BodyExpr 在这种情况会发生异常,因为这将表明编译器中的错误 - 用户代码不能创建这种情况。
附加的补丁对编译时间的影响最小:它为每个具有隐式 do 的表达式分析增加了额外的方法调用和额外的一个 cons 单元分配。它不会对生成的代码产生影响(除了修复了此票据开头指示的错误之外)。
包括三个测试,这些测试在补丁之前失败但在补丁之后成功。