From 78c3bfd2ec49a26604cc2eedb445555efaac14fe Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 6 Jul 2016 15:44:51 +0200 Subject: SI-8561 named subclasses for known Manifest / ClassTag instances This helps keeping ClassTag serialization stable under accidental changes (like changing the order of definitions, which would change the name of the anonymous classes). --- src/library/scala/reflect/ClassTag.scala | 4 +- src/library/scala/reflect/Manifest.scala | 113 ++++++++++++++++++------------- 2 files changed, 69 insertions(+), 48 deletions(-) (limited to 'src/library') diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala index 1811d3a00f..3a300e0593 100644 --- a/src/library/scala/reflect/ClassTag.scala +++ b/src/library/scala/reflect/ClassTag.scala @@ -134,6 +134,8 @@ object ClassTag { val Nothing : ClassTag[scala.Nothing] = Manifest.Nothing val Null : ClassTag[scala.Null] = Manifest.Null + private class GenericClassTag[T](val runtimeClass: jClass[_]) extends ClassTag[T] + def apply[T](runtimeClass1: jClass[_]): ClassTag[T] = runtimeClass1 match { case java.lang.Byte.TYPE => ClassTag.Byte.asInstanceOf[ClassTag[T]] @@ -148,7 +150,7 @@ object ClassTag { case ObjectTYPE => ClassTag.Object.asInstanceOf[ClassTag[T]] case NothingTYPE => ClassTag.Nothing.asInstanceOf[ClassTag[T]] case NullTYPE => ClassTag.Null.asInstanceOf[ClassTag[T]] - case _ => new ClassTag[T]{ def runtimeClass = runtimeClass1 } + case _ => new GenericClassTag[T](runtimeClass1) } def unapply[T](ctag: ClassTag[T]): Option[Class[_]] = Some(ctag.runtimeClass) diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index 369676c273..9c38864194 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -9,7 +9,7 @@ package scala package reflect -import scala.collection.mutable.{ ArrayBuilder, WrappedArray } +import scala.collection.mutable.{ArrayBuilder, WrappedArray} /** A `Manifest[T]` is an opaque descriptor for type T. Its supported use * is to give access to the erasure of the type as a `Class` instance, as @@ -21,23 +21,22 @@ import scala.collection.mutable.{ ArrayBuilder, WrappedArray } * which are not yet adequately represented in manifests. * * Example usages: -{{{ - def arr[T] = new Array[T](0) // does not compile - def arr[T](implicit m: Manifest[T]) = new Array[T](0) // compiles - def arr[T: Manifest] = new Array[T](0) // shorthand for the preceding - - // Methods manifest, classManifest, and optManifest are in [[scala.Predef]]. - def isApproxSubType[T: Manifest, U: Manifest] = manifest[T] <:< manifest[U] - isApproxSubType[List[String], List[AnyRef]] // true - isApproxSubType[List[String], List[Int]] // false - - def methods[T: ClassManifest] = classManifest[T].erasure.getMethods - def retType[T: ClassManifest](name: String) = - methods[T] find (_.getName == name) map (_.getGenericReturnType) - - retType[Map[_, _]]("values") // Some(scala.collection.Iterable) -}}} + * {{{ + * def arr[T] = new Array[T](0) // does not compile + * def arr[T](implicit m: Manifest[T]) = new Array[T](0) // compiles + * def arr[T: Manifest] = new Array[T](0) // shorthand for the preceding * + * // Methods manifest, classManifest, and optManifest are in [[scala.Predef]]. + * def isApproxSubType[T: Manifest, U: Manifest] = manifest[T] <:< manifest[U] + * isApproxSubType[List[String], List[AnyRef]] // true + * isApproxSubType[List[String], List[Int]] // false + * + * def methods[T: ClassManifest] = classManifest[T].erasure.getMethods + * def retType[T: ClassManifest](name: String) = + * methods[T] find (_.getName == name) map (_.getGenericReturnType) + * + * retType[Map[_, _]]("values") // Some(scala.collection.Iterable) + * }}} */ @scala.annotation.implicitNotFound(msg = "No Manifest available for ${T}.") // TODO undeprecated until Scala reflection becomes non-experimental @@ -88,71 +87,79 @@ object ManifestFactory { def valueManifests: List[AnyValManifest[_]] = List(Byte, Short, Char, Int, Long, Float, Double, Boolean, Unit) - val Byte: AnyValManifest[Byte] = new AnyValManifest[scala.Byte]("Byte") { + private class ByteManifest extends AnyValManifest[scala.Byte]("Byte") { def runtimeClass = java.lang.Byte.TYPE override def newArray(len: Int): Array[Byte] = new Array[Byte](len) override def newWrappedArray(len: Int): WrappedArray[Byte] = new WrappedArray.ofByte(new Array[Byte](len)) override def newArrayBuilder(): ArrayBuilder[Byte] = new ArrayBuilder.ofByte() private def readResolve(): Any = Manifest.Byte } + val Byte: AnyValManifest[Byte] = new ByteManifest - val Short: AnyValManifest[Short] = new AnyValManifest[scala.Short]("Short") { + private class ShortManifest extends AnyValManifest[scala.Short]("Short") { def runtimeClass = java.lang.Short.TYPE override def newArray(len: Int): Array[Short] = new Array[Short](len) override def newWrappedArray(len: Int): WrappedArray[Short] = new WrappedArray.ofShort(new Array[Short](len)) override def newArrayBuilder(): ArrayBuilder[Short] = new ArrayBuilder.ofShort() private def readResolve(): Any = Manifest.Short } + val Short: AnyValManifest[Short] = new ShortManifest - val Char: AnyValManifest[Char] = new AnyValManifest[scala.Char]("Char") { + private class CharManifest extends AnyValManifest[scala.Char]("Char") { def runtimeClass = java.lang.Character.TYPE override def newArray(len: Int): Array[Char] = new Array[Char](len) override def newWrappedArray(len: Int): WrappedArray[Char] = new WrappedArray.ofChar(new Array[Char](len)) override def newArrayBuilder(): ArrayBuilder[Char] = new ArrayBuilder.ofChar() private def readResolve(): Any = Manifest.Char } + val Char: AnyValManifest[Char] = new CharManifest - val Int: AnyValManifest[Int] = new AnyValManifest[scala.Int]("Int") { + private class IntManifest extends AnyValManifest[scala.Int]("Int") { def runtimeClass = java.lang.Integer.TYPE override def newArray(len: Int): Array[Int] = new Array[Int](len) override def newWrappedArray(len: Int): WrappedArray[Int] = new WrappedArray.ofInt(new Array[Int](len)) override def newArrayBuilder(): ArrayBuilder[Int] = new ArrayBuilder.ofInt() private def readResolve(): Any = Manifest.Int } + val Int: AnyValManifest[Int] = new IntManifest - val Long: AnyValManifest[Long] = new AnyValManifest[scala.Long]("Long") { + private class LongManifest extends AnyValManifest[scala.Long]("Long") { def runtimeClass = java.lang.Long.TYPE override def newArray(len: Int): Array[Long] = new Array[Long](len) override def newWrappedArray(len: Int): WrappedArray[Long] = new WrappedArray.ofLong(new Array[Long](len)) override def newArrayBuilder(): ArrayBuilder[Long] = new ArrayBuilder.ofLong() private def readResolve(): Any = Manifest.Long } + val Long: AnyValManifest[Long] = new LongManifest - val Float: AnyValManifest[Float] = new AnyValManifest[scala.Float]("Float") { + private class FloatManifest extends AnyValManifest[scala.Float]("Float") { def runtimeClass = java.lang.Float.TYPE override def newArray(len: Int): Array[Float] = new Array[Float](len) override def newWrappedArray(len: Int): WrappedArray[Float] = new WrappedArray.ofFloat(new Array[Float](len)) override def newArrayBuilder(): ArrayBuilder[Float] = new ArrayBuilder.ofFloat() private def readResolve(): Any = Manifest.Float } + val Float: AnyValManifest[Float] = new FloatManifest - val Double: AnyValManifest[Double] = new AnyValManifest[scala.Double]("Double") { + private class DoubleManifest extends AnyValManifest[scala.Double]("Double") { def runtimeClass = java.lang.Double.TYPE override def newArray(len: Int): Array[Double] = new Array[Double](len) override def newWrappedArray(len: Int): WrappedArray[Double] = new WrappedArray.ofDouble(new Array[Double](len)) override def newArrayBuilder(): ArrayBuilder[Double] = new ArrayBuilder.ofDouble() private def readResolve(): Any = Manifest.Double } + val Double: AnyValManifest[Double] = new DoubleManifest - val Boolean: AnyValManifest[Boolean] = new AnyValManifest[scala.Boolean]("Boolean") { + private class BooleanManifest extends AnyValManifest[scala.Boolean]("Boolean") { def runtimeClass = java.lang.Boolean.TYPE override def newArray(len: Int): Array[Boolean] = new Array[Boolean](len) override def newWrappedArray(len: Int): WrappedArray[Boolean] = new WrappedArray.ofBoolean(new Array[Boolean](len)) override def newArrayBuilder(): ArrayBuilder[Boolean] = new ArrayBuilder.ofBoolean() private def readResolve(): Any = Manifest.Boolean } + val Boolean: AnyValManifest[Boolean] = new BooleanManifest - val Unit: AnyValManifest[Unit] = new AnyValManifest[scala.Unit]("Unit") { + private class UnitManifest extends AnyValManifest[scala.Unit]("Unit") { def runtimeClass = java.lang.Void.TYPE override def newArray(len: Int): Array[Unit] = new Array[Unit](len) override def newWrappedArray(len: Int): WrappedArray[Unit] = new WrappedArray.ofUnit(new Array[Unit](len)) @@ -162,43 +169,49 @@ object ManifestFactory { else super.arrayClass(tp) private def readResolve(): Any = Manifest.Unit } + val Unit: AnyValManifest[Unit] = new UnitManifest private val ObjectTYPE = classOf[java.lang.Object] private val NothingTYPE = classOf[scala.runtime.Nothing$] private val NullTYPE = classOf[scala.runtime.Null$] - val Any: Manifest[scala.Any] = new PhantomManifest[scala.Any](ObjectTYPE, "Any") { + private class AnyManifest extends PhantomManifest[scala.Any](ObjectTYPE, "Any") { override def newArray(len: Int) = new Array[scala.Any](len) override def <:<(that: ClassManifest[_]): Boolean = (that eq this) private def readResolve(): Any = Manifest.Any } + val Any: Manifest[scala.Any] = new AnyManifest - val Object: Manifest[java.lang.Object] = new PhantomManifest[java.lang.Object](ObjectTYPE, "Object") { + private class ObjectManifest extends PhantomManifest[java.lang.Object](ObjectTYPE, "Object") { override def newArray(len: Int) = new Array[java.lang.Object](len) override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) private def readResolve(): Any = Manifest.Object } + val Object: Manifest[java.lang.Object] = new ObjectManifest val AnyRef: Manifest[scala.AnyRef] = Object.asInstanceOf[Manifest[scala.AnyRef]] - val AnyVal: Manifest[scala.AnyVal] = new PhantomManifest[scala.AnyVal](ObjectTYPE, "AnyVal") { + private class AnyValPhantomManifest extends PhantomManifest[scala.AnyVal](ObjectTYPE, "AnyVal") { override def newArray(len: Int) = new Array[scala.AnyVal](len) override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) private def readResolve(): Any = Manifest.AnyVal } + val AnyVal: Manifest[scala.AnyVal] = new AnyValPhantomManifest - val Null: Manifest[scala.Null] = new PhantomManifest[scala.Null](NullTYPE, "Null") { + private class NullManifest extends PhantomManifest[scala.Null](NullTYPE, "Null") { override def newArray(len: Int) = new Array[scala.Null](len) override def <:<(that: ClassManifest[_]): Boolean = (that ne null) && (that ne Nothing) && !(that <:< AnyVal) private def readResolve(): Any = Manifest.Null } + val Null: Manifest[scala.Null] = new NullManifest - val Nothing: Manifest[scala.Nothing] = new PhantomManifest[scala.Nothing](NothingTYPE, "Nothing") { + private class NothingManifest extends PhantomManifest[scala.Nothing](NothingTYPE, "Nothing") { override def newArray(len: Int) = new Array[scala.Nothing](len) override def <:<(that: ClassManifest[_]): Boolean = (that ne null) private def readResolve(): Any = Manifest.Nothing } + val Nothing: Manifest[scala.Nothing] = new NothingManifest private class SingletonTypeManifest[T <: AnyRef](value: AnyRef) extends Manifest[T] { lazy val runtimeClass = value.getClass @@ -251,31 +264,37 @@ object ManifestFactory { def arrayType[T](arg: Manifest[_]): Manifest[Array[T]] = arg.asInstanceOf[Manifest[T]].arrayManifest + private class AbstractTypeManifest[T](prefix: Manifest[_], name: String, upperBound: Predef.Class[_], args: Seq[Manifest[_]]) extends Manifest[T] { + def runtimeClass = upperBound + override val typeArguments = args.toList + override def toString = prefix.toString+"#"+name+argString + } + /** Manifest for the abstract type `prefix # name`. `upperBound` is not * strictly necessary as it could be obtained by reflection. It was * added so that erasure can be calculated without reflection. */ def abstractType[T](prefix: Manifest[_], name: String, upperBound: Predef.Class[_], args: Manifest[_]*): Manifest[T] = - new Manifest[T] { - def runtimeClass = upperBound - override val typeArguments = args.toList - override def toString = prefix.toString+"#"+name+argString - } + new AbstractTypeManifest[T](prefix, name, upperBound, args) + + private class WildcardManifest[T](lowerBound: Manifest[_], upperBound: Manifest[_]) extends Manifest[T] { + def runtimeClass = upperBound.runtimeClass + override def toString = + "_" + + (if (lowerBound eq Nothing) "" else " >: "+lowerBound) + + (if (upperBound eq Nothing) "" else " <: "+upperBound) + } /** Manifest for the unknown type `_ >: L <: U` in an existential. */ def wildcardType[T](lowerBound: Manifest[_], upperBound: Manifest[_]): Manifest[T] = - new Manifest[T] { - def runtimeClass = upperBound.runtimeClass - override def toString = - "_" + - (if (lowerBound eq Nothing) "" else " >: "+lowerBound) + - (if (upperBound eq Nothing) "" else " <: "+upperBound) - } + new WildcardManifest[T](lowerBound, upperBound) + + private class IntersectionTypeManifest[T](parents: Seq[Manifest[_]]) extends Manifest[T] { + def runtimeClass = parents.head.runtimeClass + override def toString = parents.mkString(" with ") + } /** Manifest for the intersection type `parents_0 with ... with parents_n`. */ def intersectionType[T](parents: Manifest[_]*): Manifest[T] = - new Manifest[T] { - def runtimeClass = parents.head.runtimeClass - override def toString = parents.mkString(" with ") - } + new IntersectionTypeManifest[T](parents) } -- cgit v1.2.3