Skip to content

Commit

Permalink
Share instance of ClassTag in a ClassValue based cache
Browse files Browse the repository at this point in the history
  • Loading branch information
retronym committed Mar 15, 2019
1 parent 6f4ee4a commit 3e621d2
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 16 deletions.
39 changes: 23 additions & 16 deletions src/library/scala/reflect/ClassTag.scala
Original file line number Diff line number Diff line change
Expand Up @@ -121,29 +121,36 @@ object ClassTag {
val Nothing : ClassTag[scala.Nothing] = Manifest.Nothing
val Null : ClassTag[scala.Null] = Manifest.Null

private[this] val cache = new ClassValue[ClassTag[_]] {
override def computeValue(runtimeClass: jClass[_]): ClassTag[_] = new GenericClassTag[AnyRef](runtimeClass)
}

@SerialVersionUID(1L)
private class GenericClassTag[T](val runtimeClass: jClass[_]) extends ClassTag[T] {
override def newArray(len: Int): Array[T] = {
java.lang.reflect.Array.newInstance(runtimeClass, len).asInstanceOf[Array[T]]
}
}

def apply[T](runtimeClass1: jClass[_]): ClassTag[T] =
runtimeClass1 match {
case java.lang.Byte.TYPE => ClassTag.Byte.asInstanceOf[ClassTag[T]]
case java.lang.Short.TYPE => ClassTag.Short.asInstanceOf[ClassTag[T]]
case java.lang.Character.TYPE => ClassTag.Char.asInstanceOf[ClassTag[T]]
case java.lang.Integer.TYPE => ClassTag.Int.asInstanceOf[ClassTag[T]]
case java.lang.Long.TYPE => ClassTag.Long.asInstanceOf[ClassTag[T]]
case java.lang.Float.TYPE => ClassTag.Float.asInstanceOf[ClassTag[T]]
case java.lang.Double.TYPE => ClassTag.Double.asInstanceOf[ClassTag[T]]
case java.lang.Boolean.TYPE => ClassTag.Boolean.asInstanceOf[ClassTag[T]]
case java.lang.Void.TYPE => ClassTag.Unit.asInstanceOf[ClassTag[T]]
case ObjectTYPE => ClassTag.Object.asInstanceOf[ClassTag[T]]
case NothingTYPE => ClassTag.Nothing.asInstanceOf[ClassTag[T]]
case NullTYPE => ClassTag.Null.asInstanceOf[ClassTag[T]]
case _ => new GenericClassTag[T](runtimeClass1)
}
def apply[T](runtimeClass1: jClass[_]): ClassTag[T] = runtimeClass1 match {
case x if x.isPrimitive => primitiveClassTag(runtimeClass1)
case ObjectTYPE => ClassTag.Object.asInstanceOf[ClassTag[T]]
case NothingTYPE => ClassTag.Nothing.asInstanceOf[ClassTag[T]]
case NullTYPE => ClassTag.Null.asInstanceOf[ClassTag[T]]
case _ => cache.get(runtimeClass1).asInstanceOf[ClassTag[T]]
}

private def primitiveClassTag[T](runtimeClass1: Class[_]): ClassTag[T] = runtimeClass1 match {
case java.lang.Byte.TYPE => ClassTag.Byte.asInstanceOf[ClassTag[T]]
case java.lang.Short.TYPE => ClassTag.Short.asInstanceOf[ClassTag[T]]
case java.lang.Character.TYPE => ClassTag.Char.asInstanceOf[ClassTag[T]]
case java.lang.Integer.TYPE => ClassTag.Int.asInstanceOf[ClassTag[T]]
case java.lang.Long.TYPE => ClassTag.Long.asInstanceOf[ClassTag[T]]
case java.lang.Float.TYPE => ClassTag.Float.asInstanceOf[ClassTag[T]]
case java.lang.Double.TYPE => ClassTag.Double.asInstanceOf[ClassTag[T]]
case java.lang.Boolean.TYPE => ClassTag.Boolean.asInstanceOf[ClassTag[T]]
case java.lang.Void.TYPE => ClassTag.Unit.asInstanceOf[ClassTag[T]]
}

def unapply[T](ctag: ClassTag[T]): Option[Class[_]] = Some(ctag.runtimeClass)
}
10 changes: 10 additions & 0 deletions test/files/run/classtags-cached.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import reflect.ClassTag

object Test {
def main(args: Array[String]): Unit = {
assert(implicitly[ClassTag[SomeClass]] eq implicitly[ClassTag[SomeClass]])
assert(implicitly[ClassTag[Array[SomeClass]]] eq implicitly[ClassTag[Array[SomeClass]]])
}
}

class SomeClass

0 comments on commit 3e621d2

Please sign in to comment.