跳至主要内容

联合和交集的新实现

摘要

在 Flow 0.28 之前,联合/交集类型的实现存在严重错误,并且是 the root cause of a lot of weird behaviors 您过去可能在使用 Flow 时遇到的问题。这些错误现在已在 0.28 中的差异落地 中得到解决。

正如您在对类型系统实现的棘手部分进行重大重写后所预期的那样,将有一段短暂的调整期:您可能会遇到一些我们将在短期内解决的难题,并且您可能会遇到一些不熟悉的错误消息。

新的错误消息

<error location> Could not decide which case to select
<location of union/intersection type>

Case 1 may work:
<location of 1st case of union/intersection type>

But if it doesn't, case 2 looks promising too:
<location of 2nd case of union/intersection type>

Please provide additional annotation(s) to determine whether case 1 works
(or consider merging it with case 2):
<location to annotate>
<location to annotate>
...

这意味着在 <error location> 处,Flow 需要做出选择:必须应用 <location of union/intersection type> 处的联合/交集类型中的一个成员,但 Flow 无法根据可用信息安全地做出选择。特别是,它无法在情况 12 之间做出决定,因此 Flow 列出了一些可以帮助它区分这两种情况的注释。

需要采取的措施

您可以通过两种方式修复错误

  • 实际去注释列出的位置。这应该是最常见的修复方法。
  • 发现情况 1 和 2 之间存在真正的、非故意的歧义,并重写联合类型中的这两个情况以消除歧义。当这种情况发生时,通常会修复大量错误。

然而,还有两种可能性

  • 不存在真正的歧义,Flow 太保守/愚蠢了。在这种情况下,继续进行注释并提交 GitHub 问题。我们计划进行大量短期后续工作以自动消除更多情况,因此随着时间的推移,您应该看到 (3) 的情况减少。
  • 您不知道发生了什么。所指出的情况没有意义。它们与您在 <error location> 处的内容不符。希望您不会经常遇到 (4),但如果您遇到,请 **提交问题**,因为这意味着实现中仍然存在潜在的错误。

如果您在 GitHub 上提交问题,请包含用于重现问题的代码。您可以使用 尝试 Flow 来轻松共享您的重现案例。

如果您对这些新错误消息的缘由和方式感到好奇,以下是“联合的命运”差异提交消息的摘录

问题

Flow 的推理引擎旨在随着约束的添加而发现更多错误...但它不是为回溯而设计的。不幸的是,检查表达式的类型与联合类型确实需要回溯:如果联合的某个分支不成功,则必须尝试下一个分支,依此类推。(对于涉及交集类型的检查也是如此。)

表达式类型可能在检查时并不完全已知,这使得情况更加复杂,因此现在看起来很有希望的分支可能在以后被证明是错误的。

解决方案

基本思想是延迟尝试分支,直到我们可以确定分支一定会失败或成功,而无需进一步信息。如果尝试分支导致失败,我们可以继续下一个分支,而无需回溯。如果分支成功,我们就完成了。最后一种情况是分支看起来很有希望,但我们无法确定,除非添加约束:在这种情况下,我们尝试其他分支,并在遇到歧义时 **退出** ...请求额外的注释以决定选择哪个分支。总的来说,这意味着 (1) 我们永远不会提交可能被证明是错误的分支,并且 (2) 始终可以选择正确的分支(如果存在),前提是注释足够多。