コンパイラのバグである可能性があると思われる、複合型で値をパターン一致させようとしたときに、(少なくとも私にとっては) ちょっと不思議なコンパイラの動作に出くわしました。ただし、バグ レポートを提出する前に、私よりも知識のある人がこれを見て、何が起こっているのかについて少し説明してくれるとうれしいです。
トレイトとケース クラスの小さな階層から始めます。
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")
^
次に、extractor の使用をインスタンス タイプのマッチングに置き換えました。
as foreach {
case _: A1 => println("a1")
case _: A2 => println("a2")
}
上記はコンパイルして実際に機能し、「a1」と「a2」を画面に出力しますが、到達できないコードに関する誤った警告を発します。
<console>:23: warning: unreachable code
case _: A2 => println("a2")
驚くべきことに、make A
notsealed
は警告を取り除きます (ただし、最初のパターン マッチはまだコンパイルされません)。
それで、ここに質問があります:
- 最初のパターン マッチはコンパイルする必要がありますか? そうでない場合、正確にはなぜですか?
- 2 番目のパターン マッチに対して出力された警告は単純に間違っているのでしょうか、それとも運が良かっただけで、このマッチが間違った分岐を取る可能性がある場合がありますか?
- バグ レポートを提出する必要がありますか、それとも以前から知られていた問題で、見逃していたのでしょうか?
2.11.7
とでテストしました2.11.8
。