errr errr - 3 months ago 20
Scala Question

Scala pattern matching on generic type with TypeTag generates a warning while ClassTag not?

I have two very similar methods. The only difference is the use of

ClassTag
and
TypeTag
:

def matchClass[A: ClassTag](v: Any) =
v match {
case a: A => "it's A"
case _ => "not A"
}

def matchType[A: TypeTag](v: Any) = ... // same code as matchClass


A compile warning will show for
matchType
, but not for
matchClass
:

abstract type pattern A is unchecked since it is eliminated by erasure case a: A


Why is there a warning? why does it show only for
TypeTag
and not
ClassTag
?

Answer

You don't see a warning for classTag because this check simply works for them:

scala> matchClass[Int]("aaa")
res82: String = not A

scala> matchClass[Int](5)
res83: String = it's A 

And doesn't work for typeTag:

scala> matchType[Int](5)
res84: String = it's A

scala> matchType[Int]("aaa")
res85: String = it's A

The reason is that for pattern matching on classTags (when it's seeing an implicit) compiler generates something like:

case a: A if classTag[A].runtimeClass.isInstance(a) => ...

There is no way to get runtimeClass for TypeTags in general case, so that's why it doesn't apply to them. Pattern matching can't match on generic (polymorphic) types because of erasure, so you can see that warning by default:

 scala> def matchGeneric[A](v: Any) =
 |     v match {
 |         case a: A => "it's A"
 |         case _ => "not A"
 |     }
<console>:28: warning: abstract type pattern A is unchecked since it is eliminated by erasure
               case a: A => "it's A"
                       ^
matchGeneric: [A](v: Any)String

UPDATE: As @Seth Tisue mentioned when a tag comes from run-time universe you can get a runtime class for it (but you gonna have to create a mirror first).