Skip to content

Commit

Permalink
Merge pull request #5264 from lrytz/t8561
Browse files Browse the repository at this point in the history
SI-8561 named subclasses for known Manifest / ClassTag instances
  • Loading branch information
lrytz committed Jul 13, 2016
2 parents 1bca386 + 78c3bfd commit 3c43a7b
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 70 deletions.
4 changes: 3 additions & 1 deletion src/library/scala/reflect/ClassTag.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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]]
Expand All @@ -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)
Expand Down
113 changes: 66 additions & 47 deletions src/library/scala/reflect/Manifest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<B>)
}}}
* {{{
* 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<B>)
* }}}
*/
@scala.annotation.implicitNotFound(msg = "No Manifest available for ${T}.")
// TODO undeprecated until Scala reflection becomes non-experimental
Expand Down Expand Up @@ -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))
Expand All @@ -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
Expand Down Expand Up @@ -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)
}

0 comments on commit 3c43a7b

Please sign in to comment.