"Type arguments do not conform to class' type parameter bounds" under specific conditions

552 Views Asked by At

Given these classes in 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

The following line produces the compile error type arguments [Object] do not conform to class P's type parameter bounds [TT >: T] (even though X >: Y):

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

Interestingly, this error does not appear in the following code:

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

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

What is the difference that I am not seeing?

I had a hunch that the compiler could not assign a type to x, but that now seems strange given that in the following code, q is happily assigned A[Y]#P[X]:

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

As far as I can tell, x should also be assigned A[Y]#P[X].

The REPL gave me what I think is a clue, but I'm not sure how:

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] } is something along the lines of B[Y]#a.P[Any] (pseudocode), which seems logically equivalent to A[Y]#P[Any]. Seems like the fact that the compiler can't turn that into A[Y]#P[Any] may be a bug?

My next hunch was that the compiler couldn't turn new B[Y](new A[Y]).p[Any] into A[Y]#P[Any] because the argument to B's constructor is polymorphic. We could define a class:

class C[T] extends A[T]

and new B[Y](new C[Y]).p[Any] would be C[Y]#P[Any]. But A[Y]#P[Any] >: C[Y]#P[Any], thus it should be safe for the compiler to assign new B[Y](...).p[Any] the type A[Y]#P[Any]. Now I'm back to being convinced that this is a compiler bug.

Another interesting detail to note is that the error disappears if the return type of B.p is changed to A[T]#P[TT].

0

There are 0 best solutions below