“在特定条件下,类型参数不符合类'类型参数边界'

时间:2017-09-10 10:42:25

标签: scala scala-2.11

在Scala 2.11.8中给出了这些类:

class A[T] {
  class P[TT >: T]

  def p[TT >: T]: P[TT] = new P[TT]
}
class B[T](val a: A[T]) {
  def p[TT >: T]: a.P[TT] = a.p[TT]
}
class X
class Y extends X

以下行产生编译错误type arguments [Object] do not conform to class P's type parameter bounds [TT >: T](即使X >: Y):

val x = new B[Y](new A[Y]).p[X]

有趣的是,此错误未出现在以下代码中:

new B[Y](new A[Y]).p[X]

val y = new B[Y](new A[Y])
val z = y.p[X]

我没有看到有什么区别?

我有一种预感,编译器无法为x分配类型,但现在看来很奇怪,因为在以下代码中,q被愉快地分配A[Y]#P[X]

val q = new A[Y].p[X]

据我所知,x也应该分配A[Y]#P[X]

REPL给了我一些我认为是线索的信息,但我不确定如何:

scala> :t new B[Y](new A[Y]).p[Any]
_6.a.P[Any] forSome { val _6: B[Y] }

_6.a.P[Any] forSome { val _6: B[Y] }类似B[Y]#a.P[Any](伪代码),在逻辑上等同于A[Y]#P[Any]。 似乎编译器无法将其转换为A[Y]#P[Any]可能是一个错误的事实?

我的下一个预感是编译器无法将new B[Y](new A[Y]).p[Any]转换为A[Y]#P[Any],因为B的构造函数的参数是多态的。我们可以定义一个类:

class C[T] extends A[T]

new B[Y](new C[Y]).p[Any]将是C[Y]#P[Any]。但是A[Y]#P[Any] >: C[Y]#P[Any],因此编译器分配new B[Y](...).p[Any]类型A[Y]#P[Any]应该是安全的。现在我又回到了确信这是一个编译器错误。

另一个值得注意的有趣细节是,如果B.p的返回类型更改为A[T]#P[TT],则错误消失。

0 个答案:

没有答案