这种表达式会导致 nil,但应该无法编译
(let ())
这种表达式会导致 nil,但应该产生一个值
(let (do 1) do)
这适用于所有具有“隐式 do”的特殊形式:try/catch/finally、letfn/let、以及fn/reify/deftype形式的集合。
对于这些特殊形式,“隐式 do”的实现方式是相应的解析器会明确地将其主体表达式委托给BodyExpr.Parser。例如,
(let (x 1) (println x) x)
调用 BodyExpr.Parser.parse() 并传递列表 '((println x) x)。然而,BodyExpr.Parser 还用于解析 like '(do (println x) x) 类型的列表,在其他上下文中。为了应对这两种情况,其 parse() 方法会跳过其第一个形式,如果此形式是 'do 符号。因此,如果一个具有“隐式 do”的特殊形式将 'do 符号作为其第一个表达式,那么该符号将被错误地丢弃。
附带的修复补丁通过在每个这样的特殊形式之前插入显式的 'do 来解决这个问题,以便BodyExpr.Parser可以无条件地假定其第一个形式是 'do 并跳过它。BodyExpr 现在抛出异常,因为如果情况不是这样,则表明编译器中存在错误——用户代码不能产生这种情况。
附带的修复补丁对编译时间的影响最小:它在每个具有隐式 do 的表达式的分析中引入了一个额外的方法调用和一个额外的 cons 单元分配。它不会对生成的代码产生影响(除了修复此票据开头指示的错误)。
有三个测试包括在内,之前未通过修复后成功。