Here is a simple example:
object MatchErasedType {
trait Supe {
self: Singleton =>
type T1
lazy val default: T1
def process(v: Any): T1 = {
v match {
case vv: T1 => vv
case _ => default
}
}
}
}
It will throw a compiler warning:
MatchErasedType.scala:13:14: the type test for Supe.this.T1 cannot be checked at runtime
The case is interesting as any instance of Supe is guaranteed to be a Singleton. So a delayed reification of process won't have any erasure. As a result, this question actually entails 2 different cases:
How to eliminate it if all instances of
Supeare specialisedSingleton, presumably without using any implicit summoning or conversion?How to eliminate it in other cases?
UPDATE 1: It should be noted that the type of v: Any cannot be known in compile-time, the call-site won't be able to provide such information. Henceforth, This question is NOT for cases when T1 cannot be resolved to a concrete class and/or runtime condition.
In Scala 2
To overcome type erasure, in Scala 2 we use
scala.reflect.ClassTag. Either (approach 1)or (approach 2)
Similarly, in Scala 3
In Scala 3
scala.reflect.Typeable(scala.reflect.TypeTest) is used instead ofClassTag. The approach 1 worksRegarding the approach 2, in Scala 3 there is no way to hide implicit by name, so let's put it into a local scope so that it will not be found in object implicit scope
ClassTag,TypeTag,shapeless.Typeable/TypeCase(Scala 2),TypeTest/Typeable, Shapeless-3Typeable(Scala 3) are standard tools to overcome type erasure. Matching types at runtime is not typical for pattern matching. If your business logic is based on types then maybe you don't need pattern matching at all, maybe type classes would be a better choiceor