在尝试使用复合类型模式匹配值时,我偶然发现了一些神秘的(至少对我而言)编译器行为,我怀疑这可能是编译器错误 . 在提交错误报告之前,如果有比我知识渊博的人能够看到这个并且可能会对正在发生的事情提供一些解释,我会很高兴 .

我们从特征和案例类的一些层次结构开始:

sealed trait A
case class A1() extends A
case class A2() extends A

sealed trait B

我们希望对复合类型的值进行操作: A with B

val a1: A with B = new A1() with B
val a2: A with B = new A2() with B
val as: Seq[A with B] = Seq(a1, a2)

首先,我尝试使用案例类提取器进行模式匹配:

Seq(a1, a2) foreach {
  case A1() => println("a1")
  case A2() => println("a2")
}

由于类型不匹配,上述内容无法编译:

<console>:21: error: constructor cannot be instantiated to expected type;
 found   : A1
 required: A with B
         case A1() => println("a1")
              ^
<console>:22: error: constructor cannot be instantiated to expected type;
 found   : A2
 required: A with B
         case A2() => println("a2")
              ^

其次,我用实例类型匹配替换了提取器用法:

as foreach {
  case _: A1 => println("a1")
  case _: A2 => println("a2")
}

以上编译并确实有效,将"a1"和"a2"打印到屏幕上,但发出有关无法访问代码的错误警告:

<console>:23: warning: unreachable code
         case _: A2 => println("a2")

令人惊讶的是,使 Asealed 摆脱了警告(尽管第一个模式匹配仍然无法编译) .

所以,问题来了:

  • 第一个模式是否匹配编译?如果没有,那为什么呢?

  • 第二个模式发出的警告是否完全错误或者我是否幸运,并且有时候这种匹配可能会出错?

  • 我应该提交一份错误报告,或者是否错过了's a long known issue I'?

我在 2.11.72.11.8 上测试了它 .