次のコード例があります。
trait Recurse[T <: Recurse[T]] {
def method = "This is a method on recurse"
}
class Foo extends Recurse[Foo] {
override def toString = "This is a foo"
}
object Example {
def generate: Recurse[_ /*<: Recurse[_]*/] = new Foo()
def main(args: Array[String]) {
val foo = generate
foo match {
case m: Foo => println("match: " + m)
case _ => println("baa")
}
println(foo.method)
}
}
このコードは、2.9.x では正しくコンパイルおよび実行されます (「一致: This is a foo」の後に「This is a method on recurse」が出力されます) が、2.10.2 では機能しません。代わりに、コンパイル時エラーが発生します: type arguments [_$1] do not conform to trait Recurse's type parameter bounds [T <: Recurse[T]]
これについて興味深いのは、問題がパターン マッチャーでのみ発生することです。match ブロックを削除すると、コードがコンパイルされ、コードは「This is a method on recurse」を出力します。
さらに興味深いのは、パターン マッチがデフォルトのケースだけであっても、コンパイルに失敗することです! コンパイラは、パターン マッチの再帰的存在型を持つオブジェクトを受け入れません。ただし、foo の値が明示的に指定されている場合 ("val foo = new Foo()")、または型パラメーターが再帰的でない場合、コードは 2.10 でもコンパイルされます。
ここで何が起こっているのですか?型パラメーターが一致にまったく関与していない場合でも、このパターン一致が壊れるのはなぜですか? これを 2.10 互換の方法で書き直す方法はありますか?