scalatype-erasurescala-reflect

Scala how to fix type erasure warning even though I added ClassTag


I am wondering how to fix the type erasure warning even though I added ClassTag? is there an easy fix without adding an additional library like TypeTag?

import scala.reflect.ClassTag

class Node
class C_PHYLUM[T]
class I_PHYLUM[T](name: String)
trait C_SEQUENCE[T1,T2]
class T_SEQUENCE[T]

class M_SEQUENCE[T_ElemType <: Node : ClassTag](name : String, t_ElemType:C_PHYLUM[T_ElemType])
  extends I_PHYLUM[T_SEQUENCE[T_ElemType]](name)
    with C_SEQUENCE[T_SEQUENCE[T_ElemType],T_ElemType]
{
  type T_Result = T_SEQUENCE[T_ElemType];
  def u__op_AC(x:Any) : Option[(T_Result,Seq[T_ElemType])] = x match {
    case x : T_Result => Some((x,toList(x)));
    case _ => None
  };

  def toList[T](x: T): Seq[T_ElemType] = Seq(x.asInstanceOf[T_ElemType])
}

Warning:

warning: abstract type T_ElemType in type pattern T_SEQUENCE[T_ElemType] (the underlying of M_SEQUENCE.this.T_Result) is unchecked since it is eliminated by erasure
    case x : T_Result => Some((x,toList(x)));

Re-producable example


Solution

  • Type erasure is a consequence of how generics are implemented on the JVM. It means that a runtime, you won't be able to tell the difference between e.g. a List[Int] and a List[String]; all the runtime knows is that you have a List. The knowledge of whether you're expecting [Int] or [String] is compile-time only.

    In your case, you have T_SEQUENCE[T_ElemType] - so given some object of type Any, you can use isInstanceOf to check if you have an instance of some T_SEQUENCE, but there's no knowledge of what the type parameter on it is.

    You could make an assumption that your method will never receive a T_SEQUENCE with the wrong type parameter, and use that to do

    case x : T_SEQUENCE[_] => Some((x.asInstanceOf[T_Result],toList(x.asInstanceOf[T_Result])))
    

    Or, assuming your T_SEQUENCE class has some kind of .map method that lets you transform the value inside, you could do something that delegates to the ClassTag that you brought in, e.g.

    // I'll assume a method like this exists:
    def transformTSeq[A, B](tSeq: T_SEQUENCE[A], f: A => Option[B]): Option[T_SEQUENCE[B]]
    
    // inside your match
    case x: T_SEQUENCE[_] =>
      transformTSeq(x, value => {
        implicitly[ClassTag[T_ElemType]].unapply(value)
      })
    case _ => 
      None
    

    P.S. get rid of those semicolons