Scala:与路径相关的类型上的模式匹配

问题描述

无法弄清楚为什么Scala 2.13对模式匹配不满意

  trait A {
    sealed trait T
    case class TImpl() extends T
  }

  trait Fail[B <: A] {
    val a: B // no error if `a: A`
    def foo(t : a.T): Unit = t match {
      case _: a.TImpl => // "match may not be exhaustive. It would fail on the following input: TImpl()"
    }
  }

有合理的解决方法吗? Dotty看起来还不错

解决方法

如果您想了解为什么原则上模式匹配不能详尽无遗,例如,请参见以下示例

trait A {
  sealed trait T
  case class TImpl() extends T
}

trait Fail[B <: A] {
  val a: B
  def foo(t : a.T): Unit = t match {
    case _: a.TImpl => 
  }
}

class B extends A
val b = new B
class FailImpl extends Fail[b.type] {
  override val a: b.type = b
}
val fail: Fail[b.type] = new FailImpl

class C
case class CImpl() extends C with b.T
val x = CImpl()
fail.foo(x) // MatchError

您可以说实际上我们没有C。好吧,编译器应该足够聪明才能弄清楚这一点。

如果要关闭警告,可以写@unchecked

def foo(t : a.T): Unit = (t: @unchecked) match {
  case _: a.TImpl => 
}

根据规范

如果模式匹配的选择器是密封类的实例,则模式匹配的编译会发出警告,从而诊断给定的一组模式不是穷举性的,即存在{{1} }在运行时引发。

https://scala-lang.org/files/archive/spec/2.13/08-pattern-matching.html#pattern-matching-expressions

编译器可以发出警告,但必须。因此,没有警告并不能保证模式匹配是详尽无遗的。