Reputation: 63
Let's start with an example code:
import scala.reflect.runtime.universe._
class A[T] {
}
def foo[T: TypeTag](a: A[T]) {
println(typeTag[T])
}
val a = new A[Int]
val b: A[_] = a
foo(a)
foo(b)
The output is:
TypeTag[Int]
TypeTag[_$1]
Well, I have no clue whatsoever what is TypeTag[_$1]
, but it sure looks fancy. :) Still, I would think foo's expectations of the world are being violated here, as in if foo gets called with an instance of A[Int]
then it is guaranteed to have the typetag for Int, and not some other obscure typetag. Also, shouldn't typetags be "concrete" in contrast to weektypetags?
Now of course I see that the compiler cannot tell in the second foo call the type parameter of A. So my expectation wasn't that I magically get typeTag[Int]
as the output of the second call, but rather I was hoping for a compile time error.
Where is my missunderstanding?
Some futile speculation
One could argue that what's going on is a call to foo with argument type A[_]
, or, to make it more explicit, the existential type A[S] forSome { type S }
. An then the typeTag captures the "_" somehow. But this doesn't really make sense, as foo expects A[T]
for some concrete T
, and the above existential type is not A[T]
for any concrete T
.
Or maybe a call with an argument A[Any]
? But then why not TypeTag[Any]
, and even more severely, A
is not covariant, so this would also be plain wrong.
Btw, I'm using scala 2.10.
Upvotes: 2
Views: 342
Reputation: 13667
Type tags are created at compile time, and values are not available at compile time. Once you cast an A[Int]
to the existential type A[_]
, all information about the type parameter has been lost.
If they were created at run-time, based on values, type erasure would make it impossible to know A
's parameter. Even something that is known to be an A[Int]
at compile-time is at best an A[Object]
at run-time (unless A
is Array
, but let's not go there).
So your speculation is correct, for foo(b)
, the type parameter is indeed the _
from the existential A[_]
, and that anonymous type variable prints as _$1
.
Upvotes: 1