Andras
Andras

Reputation: 63

Scala reflection: TypeTag from context bound doesn't match type parameter

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

Answers (1)

wingedsubmariner
wingedsubmariner

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

Related Questions