Intellij不会捕获使用函数作为防护的非详尽匹配

CPS*_*CPS 1 scala intellij-idea

我在我们的代码库中找到了以下代码块:

val appId: (String, Option[String]) = request.app match {
  case Some(app) if hasAppId(app) => (Constants.AppId, app.id)
  case None => (Constants.AppId, None)
}
Run Code Online (Sandbox Code Playgroud)

hasAppId返回一个布尔值。显然,这种匹配并不详尽,但是没有编译器警告。如果我把警卫换成

case Some(app) if false =>
Run Code Online (Sandbox Code Playgroud)

我得到了预期的警告。为什么Intellij无法检测到这种非详尽的匹配?

编辑:这是hasAppId的定义。注意显式的布尔返回:

def hasAppId(app: App): Boolean = app.id.isDefined && !app.id.get.isEmpty
Run Code Online (Sandbox Code Playgroud)

Ben*_*ich 5

这与IntelliJ无关,只是Scala编译器的限制。

只要存在非平凡的if子句,警告就不会出现。您甚至可以在REPL中尝试以下操作:

Option(1) match { case Some(x) => ??? } //warning
Option(1) match { case Some(x) if Math.random > 0.5 => ??? } //no warning
Run Code Online (Sandbox Code Playgroud)

编写if false(或if 1==1其他简单表达式)时未得到警告的原因是由于常量折叠,编译器可以在编译过程的较早阶段删除或合并常量。

请记住,这些只是警告,不能期望编译器完全理解匹配何时可能是详尽无遗的。这个例子特别简单,但是在更复杂的例子中,这个逻辑可能是完全不重要的。在我看来,编译器甚至不会尝试if对进行任何声明case,并且您看到的情况纯粹是由于不断折叠造成的。

语言规范在此处提到了这一点,它表示编译器可以发出警告:

如果模式匹配的选择器是密封类的实例,则模式匹配的编译会发出警告,该警告会诊断给定的一组模式不是穷举性的,即MatchError在运行时可能会引起警告。