Reputation: 20653
The following Scala code, using the recursive type A
does not compile:
package reflection.scala.stackOverflow
import scala.reflect.runtime.universe._
class A[T<:A[T]]
class Question(root:A[_]) {
val rtmMirror =runtimeMirror(getClass.getClassLoader)
val instanceMirror : InstanceMirror =rtmMirror.reflect(root)
}
It gives the following compilation error:
Error:(9, 50) type arguments [_$1] do not conform to class A's type parameter bounds [T <: reflection.scala.stackOverflow.A[T]]
val instanceMirror : InstanceMirror =rtmMirror.reflect(root)
^
Error:(9, 57) type arguments [_$1] do not conform to class A's type parameter bounds [T <: reflection.scala.stackOverflow.A[T]]
val instanceMirror : InstanceMirror =rtmMirror.reflect(root)
^
Why does the compilation fail?
What is the type argument $1 here ?
Where does $1 come from ?
Why does $1 not conform to A's type parameter bounds ?
How can this code be modified so that it compiles while preserving compile time type checking of root
to be a type of A
?
Upvotes: 2
Views: 144
Reputation: 39577
If you really don't care:
scala> import scala.reflect.runtime._
import scala.reflect.runtime._
scala> import universe._
import universe._
scala> class A[T<:A[T]] { def a: T = null.asInstanceOf[T] }
defined class A
scala> def f(x: A[_]) = currentMirror reflect[A[_]] x
f: (x: A[_])reflect.runtime.universe.InstanceMirror
scala> f(new A)
res0: reflect.runtime.universe.InstanceMirror = instance mirror for A@5b369cb9
scala> typeOf[A[_]].member(TermName("a")).asMethod
res1: reflect.runtime.universe.MethodSymbol = method a
scala> res0 reflectMethod res1
res2: reflect.runtime.universe.MethodMirror = method mirror for A.a: T (bound to A@5b369cb9)
scala> res2()
res3: Any = null
I want a black distressed tee that has on the front X[_]
and on the back, I dont care what type you think I am.
Maybe more strongly worded.
Upvotes: 1
Reputation: 167891
If you don't tell it that the argument of A
is of the right type, it will fill in an anonymous type parameter (the _$1
is an anonymous type used for the argument of A
) and won't necessarily make it as specific as it needs to be . Just specify a valid type yourself instead:
class Question[T <: A[T]](root: A[T])
and the compiler will be happy.
Upvotes: 2