Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SI-8561 named subclasses for known Manifest / ClassTag instances #5264

Merged
merged 1 commit into from
Jul 13, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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)
}