実装で上限を変更したときに、この奇妙な動作に遭遇しましたが、インターフェイスで変更するのを忘れていました。最後のステートメントはコンパイルすべきではないと思いますが、コンパイルして予期しない結果を返します。
trait SuperBase
trait Base extends SuperBase
class SuperBaseImpl extends SuperBase
trait Service {
def doWork[T <: Base : Manifest](body: T => Unit): String
def print[T <: Base : Manifest]: String
}
object ServiceImpl extends Service {
override def doWork[T <: SuperBase : Manifest](body: T => Unit): String =
print[T]
def print[T <: SuperBase : Manifest]: String =
manifest[T].runtimeClass.toString
}
val s: Service = ServiceImpl
// does not compile as expected
// s.print[SuperBaseImpl]
// returns "interface Base"
s.doWork { x: SuperBaseImpl => () }
編集
@som-snytt が-Xprint:typer
オプションで言及したように、コンパイラが実際に何を推論するかを確認できます。
s.doWork[Base with SuperBaseImpl]
これは、「インターフェイス ベース」を取得する理由を説明しています。しかし、この場合、型推論がどのように、なぜ機能するのか、まだよくわかりません。