summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
Diffstat (limited to 'src/library')
-rw-r--r--src/library/scala/Predef.scala26
-rw-r--r--src/library/scala/reflect/ArrayTag.scala8
-rw-r--r--src/library/scala/reflect/ClassTag.scala206
-rw-r--r--src/library/scala/reflect/DummyMirror.scala2
-rw-r--r--src/library/scala/reflect/ErasureTag.scala23
-rw-r--r--src/library/scala/reflect/ReflectionUtils.scala1
-rw-r--r--src/library/scala/reflect/TagMaterialization.scala122
-rwxr-xr-xsrc/library/scala/reflect/api/Symbols.scala8
-rw-r--r--src/library/scala/reflect/api/TypeTags.scala246
-rwxr-xr-xsrc/library/scala/reflect/api/Universe.scala23
-rw-r--r--src/library/scala/reflect/makro/Context.scala21
-rw-r--r--src/library/scala/reflect/makro/Reifiers.scala25
-rw-r--r--src/library/scala/reflect/makro/internal/Utils.scala86
-rw-r--r--src/library/scala/reflect/package.scala5
-rw-r--r--src/library/scala/runtime/ScalaRunTime.scala21
-rw-r--r--src/library/scala/util/Marshal.scala36
16 files changed, 334 insertions, 525 deletions
diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala
index 15e007528b..093f972f72 100644
--- a/src/library/scala/Predef.scala
+++ b/src/library/scala/Predef.scala
@@ -119,20 +119,24 @@ object Predef extends LowPriorityImplicits {
def optManifest[T](implicit m: OptManifest[T]) = m
// Tag types and companions, and incantations for summoning
- type ClassTag[T] = scala.reflect.ClassTag[T]
- type TypeTag[T] = scala.reflect.TypeTag[T]
- type ConcreteTypeTag[T] = scala.reflect.ConcreteTypeTag[T]
- val ClassTag = scala.reflect.ClassTag // doesn't need to be lazy, because it's not a path-dependent type
+ type ArrayTag[T] = scala.reflect.ArrayTag[T]
+ type ErasureTag[T] = scala.reflect.ErasureTag[T]
+ type ClassTag[T] = scala.reflect.ClassTag[T]
+ type TypeTag[T] = scala.reflect.TypeTag[T]
+ type ConcreteTypeTag[T] = scala.reflect.ConcreteTypeTag[T]
+ val ClassTag = scala.reflect.ClassTag // doesn't need to be lazy, because it's not a path-dependent type
// [Paul to Eugene] No lazy vals in Predef. Too expensive. Have to work harder on breaking initialization dependencies.
- lazy val TypeTag = scala.reflect.TypeTag // needs to be lazy, because requires scala.reflect.mirror instance
- lazy val ConcreteTypeTag = scala.reflect.ConcreteTypeTag
+ lazy val TypeTag = scala.reflect.TypeTag // needs to be lazy, because requires scala.reflect.mirror instance
+ lazy val ConcreteTypeTag = scala.reflect.ConcreteTypeTag
// [Eugene to Martin] it's really tedious to type "implicitly[...]" all the time, so I'm reintroducing these shortcuts
- def classTag[T](implicit ctag: ClassTag[T]) = ctag
- def tag[T](implicit ttag: TypeTag[T]) = ttag
- def typeTag[T](implicit ttag: TypeTag[T]) = ttag
- def concreteTag[T](implicit cttag: ConcreteTypeTag[T]) = cttag
- def concreteTypeTag[T](implicit cttag: ConcreteTypeTag[T]) = cttag
+ def arrayTag[T](implicit atag: ArrayTag[T]) = atag
+ def erasureTag[T](implicit etag: ErasureTag[T]) = etag
+ def classTag[T](implicit ctag: ClassTag[T]) = ctag
+ def tag[T](implicit ttag: TypeTag[T]) = ttag
+ def typeTag[T](implicit ttag: TypeTag[T]) = ttag
+ def concreteTag[T](implicit cttag: ConcreteTypeTag[T]) = cttag
+ def concreteTypeTag[T](implicit cttag: ConcreteTypeTag[T]) = cttag
// Minor variations on identity functions
def identity[A](x: A): A = x // @see `conforms` for the implicit version
diff --git a/src/library/scala/reflect/ArrayTag.scala b/src/library/scala/reflect/ArrayTag.scala
index 8df7fe5f4e..ba0c075723 100644
--- a/src/library/scala/reflect/ArrayTag.scala
+++ b/src/library/scala/reflect/ArrayTag.scala
@@ -3,11 +3,17 @@ package scala.reflect
/** An `ArrayTag[T]` is a descriptor that is requested by the compiler every time
* when an array is instantiated, but the element type is unknown at compile time.
*
+ * Implicit in the contract of `ArrayTag[T]` is the fact that `T`
+ * cannot contain unresolved references to type parameters or abstract types.
+ *
* Scala library provides a standard implementation of this trait,
- * `ClassTag[T]` that explicitly carries the `java.lang.Class` erasure of type T.
+ * `ClassTag[T]` that explicitly carries the `java.lang.Class` erasure of type T
+ * and uses Java reflection to instantiate arrays.
*
* However other platforms (e.g. a Scala -> JS crosscompiler) may reimplement this trait as they see fit
* and then expose the implementation via an implicit macro.
+ *
+ * @see [[scala.reflect.api.TypeTags]]
*/
@annotation.implicitNotFound(msg = "No ArrayTag available for ${T}")
trait ArrayTag[T] {
diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala
index 142025f600..e485691747 100644
--- a/src/library/scala/reflect/ClassTag.scala
+++ b/src/library/scala/reflect/ClassTag.scala
@@ -3,6 +3,7 @@ package scala.reflect
import java.lang.{ Class => jClass }
import scala.reflect.{ mirror => rm }
import language.{implicitConversions, existentials}
+import scala.runtime.ScalaRunTime.arrayClass
/** A `ClassTag[T]` wraps a Java class, which can be accessed via the `erasure` method.
*
@@ -18,34 +19,17 @@ import language.{implicitConversions, existentials}
* If the type T contains unresolved references to type parameters or abstract types, a static error results.
*
* A ConcreteTypeTag member of the reflect.mirror object is convertible to a ClassTag via an implicit conversion
- * (this is not possible to do in all reflection universes because an operation that converts a type to a Java class might not be available). */
-// please, don't add any APIs here, like it was with `newWrappedArray` and `newArrayBuilder`
-// class tags, and all tags in general, should be as minimalistic as possible
+ * (this is not possible to do in all reflection universes because an operation that converts a type to a Java class might not be available).
+ *
+ * @see [[scala.reflect.api.TypeTags]]
+ */
@annotation.implicitNotFound(msg = "No ClassTag available for ${T}")
-abstract case class ClassTag[T](erasure: jClass[_]) extends ArrayTag[T] {
- // quick and dirty fix to a deadlock in Predef:
- // http://groups.google.com/group/scala-internals/browse_thread/thread/977de028a4e75d6f
- // todo. fix that in a sane way
- // assert(erasure != null)
-
- /** A Scala reflection type representing T.
- * For ClassTags this representation is lossy (in their case tpe is retrospectively constructed from erasure).
- * For TypeTags and ConcreteTypeTags the representation is almost precise, because they use reification
- * (information is lost only when T refers to non-locatable symbols, which are then reified as free variables). */
- def tpe: rm.Type = rm.classToType(erasure)
-
- /** A Scala reflection symbol representing T. */
- def symbol: rm.Symbol = rm.classToSymbol(erasure)
+trait ClassTag[T] extends ArrayTag[T] with ErasureTag[T] with Equals with Serializable {
+ // please, don't add any APIs here, like it was with `newWrappedArray` and `newArrayBuilder`
+ // class tags, and all tags in general, should be as minimalistic as possible
/** Produces a `ClassTag` that knows how to build `Array[Array[T]]` */
- def wrap: ClassTag[Array[T]] = {
- // newInstance throws an exception if the erasure is Void.TYPE
- // see SI-5680
- val arrayClazz =
- if (erasure == java.lang.Void.TYPE) classOf[Array[Unit]]
- else java.lang.reflect.Array.newInstance(erasure, 0).getClass.asInstanceOf[jClass[Array[T]]]
- ClassTag[Array[T]](arrayClazz)
- }
+ def wrap: ClassTag[Array[T]] = ClassTag[Array[T]](arrayClass(erasure))
/** Produces a new array with element type `T` and length `len` */
def newArray(len: Int): Array[T] =
@@ -61,31 +45,39 @@ abstract case class ClassTag[T](erasure: jClass[_]) extends ArrayTag[T] {
case java.lang.Void.TYPE => new Array[Unit](len).asInstanceOf[Array[T]]
case _ => java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[T]]
}
+
+ /** case class accessories */
+ override def canEqual(x: Any) = x.isInstanceOf[ClassTag[_]]
+ override def equals(x: Any) = x.isInstanceOf[ClassTag[_]] && this.erasure == x.asInstanceOf[ClassTag[_]].erasure
+ override def hashCode = scala.runtime.ScalaRunTime.hash(erasure)
+ override def toString = "ClassTag[" + erasure + "]"
}
object ClassTag {
+ private val NothingTYPE = classOf[scala.runtime.Nothing$]
+ private val NullTYPE = classOf[scala.runtime.Null$]
private val ObjectTYPE = classOf[java.lang.Object]
private val StringTYPE = classOf[java.lang.String]
- val Byte : ClassTag[scala.Byte] = new ClassTag[scala.Byte](java.lang.Byte.TYPE) { private def readResolve() = ClassTag.Byte }
- val Short : ClassTag[scala.Short] = new ClassTag[scala.Short](java.lang.Short.TYPE) { private def readResolve() = ClassTag.Short }
- val Char : ClassTag[scala.Char] = new ClassTag[scala.Char](java.lang.Character.TYPE) { private def readResolve() = ClassTag.Char }
- val Int : ClassTag[scala.Int] = new ClassTag[scala.Int](java.lang.Integer.TYPE) { private def readResolve() = ClassTag.Int }
- val Long : ClassTag[scala.Long] = new ClassTag[scala.Long](java.lang.Long.TYPE) { private def readResolve() = ClassTag.Long }
- val Float : ClassTag[scala.Float] = new ClassTag[scala.Float](java.lang.Float.TYPE) { private def readResolve() = ClassTag.Float }
- val Double : ClassTag[scala.Double] = new ClassTag[scala.Double](java.lang.Double.TYPE) { private def readResolve() = ClassTag.Double }
- val Boolean : ClassTag[scala.Boolean] = new ClassTag[scala.Boolean](java.lang.Boolean.TYPE) { private def readResolve() = ClassTag.Boolean }
- val Unit : ClassTag[scala.Unit] = new ClassTag[scala.Unit](java.lang.Void.TYPE) { private def readResolve() = ClassTag.Unit }
- val Any : ClassTag[scala.Any] = new ClassTag[scala.Any](ObjectTYPE) { private def readResolve() = ClassTag.Any }
- val Object : ClassTag[java.lang.Object] = new ClassTag[java.lang.Object](ObjectTYPE) { private def readResolve() = ClassTag.Object }
- val AnyVal : ClassTag[scala.AnyVal] = new ClassTag[scala.AnyVal](ObjectTYPE) { private def readResolve() = ClassTag.AnyVal }
- val AnyRef : ClassTag[scala.AnyRef] = new ClassTag[scala.AnyRef](ObjectTYPE) { private def readResolve() = ClassTag.AnyRef }
- val Nothing : ClassTag[scala.Nothing] = new ClassTag[scala.Nothing](ObjectTYPE) { private def readResolve() = ClassTag.Nothing }
- val Null : ClassTag[scala.Null] = new ClassTag[scala.Null](ObjectTYPE) { private def readResolve() = ClassTag.Null }
- val String : ClassTag[java.lang.String] = new ClassTag[java.lang.String](StringTYPE) { private def readResolve() = ClassTag.String }
-
- def apply[T](clazz: jClass[_]): ClassTag[T] =
- clazz match {
+ val Byte : ClassTag[scala.Byte] = new ClassTag[scala.Byte]{ def erasure = java.lang.Byte.TYPE; private def readResolve() = ClassTag.Byte }
+ val Short : ClassTag[scala.Short] = new ClassTag[scala.Short]{ def erasure = java.lang.Short.TYPE; private def readResolve() = ClassTag.Short }
+ val Char : ClassTag[scala.Char] = new ClassTag[scala.Char]{ def erasure = java.lang.Character.TYPE; private def readResolve() = ClassTag.Char }
+ val Int : ClassTag[scala.Int] = new ClassTag[scala.Int]{ def erasure = java.lang.Integer.TYPE; private def readResolve() = ClassTag.Int }
+ val Long : ClassTag[scala.Long] = new ClassTag[scala.Long]{ def erasure = java.lang.Long.TYPE; private def readResolve() = ClassTag.Long }
+ val Float : ClassTag[scala.Float] = new ClassTag[scala.Float]{ def erasure = java.lang.Float.TYPE; private def readResolve() = ClassTag.Float }
+ val Double : ClassTag[scala.Double] = new ClassTag[scala.Double]{ def erasure = java.lang.Double.TYPE; private def readResolve() = ClassTag.Double }
+ val Boolean : ClassTag[scala.Boolean] = new ClassTag[scala.Boolean]{ def erasure = java.lang.Boolean.TYPE; private def readResolve() = ClassTag.Boolean }
+ val Unit : ClassTag[scala.Unit] = new ClassTag[scala.Unit]{ def erasure = java.lang.Void.TYPE; private def readResolve() = ClassTag.Unit }
+ val Any : ClassTag[scala.Any] = new ClassTag[scala.Any]{ def erasure = ObjectTYPE; private def readResolve() = ClassTag.Any }
+ val Object : ClassTag[java.lang.Object] = new ClassTag[java.lang.Object]{ def erasure = ObjectTYPE; private def readResolve() = ClassTag.Object }
+ val AnyVal : ClassTag[scala.AnyVal] = new ClassTag[scala.AnyVal]{ def erasure = ObjectTYPE; private def readResolve() = ClassTag.AnyVal }
+ val AnyRef : ClassTag[scala.AnyRef] = new ClassTag[scala.AnyRef]{ def erasure = ObjectTYPE; private def readResolve() = ClassTag.AnyRef }
+ val Nothing : ClassTag[scala.Nothing] = new ClassTag[scala.Nothing]{ def erasure = NothingTYPE; private def readResolve() = ClassTag.Nothing }
+ val Null : ClassTag[scala.Null] = new ClassTag[scala.Null]{ def erasure = NullTYPE; private def readResolve() = ClassTag.Null }
+ val String : ClassTag[java.lang.String] = new ClassTag[java.lang.String]{ def erasure = StringTYPE; private def readResolve() = ClassTag.String }
+
+ def apply[T](erasure1: jClass[_]): ClassTag[T] =
+ erasure1 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]]
@@ -97,128 +89,8 @@ object ClassTag {
case java.lang.Void.TYPE => ClassTag.Unit.asInstanceOf[ClassTag[T]]
case ObjectTYPE => ClassTag.Object.asInstanceOf[ClassTag[T]]
case StringTYPE => ClassTag.String.asInstanceOf[ClassTag[T]]
- case _ => new ClassTag[T](clazz) {}
- }
-
- def apply[T](tpe: rm.Type): ClassTag[T] =
- tpe match {
- case rm.ByteTpe => ClassTag.Byte.asInstanceOf[ClassTag[T]]
- case rm.ShortTpe => ClassTag.Short.asInstanceOf[ClassTag[T]]
- case rm.CharTpe => ClassTag.Char.asInstanceOf[ClassTag[T]]
- case rm.IntTpe => ClassTag.Int.asInstanceOf[ClassTag[T]]
- case rm.LongTpe => ClassTag.Long.asInstanceOf[ClassTag[T]]
- case rm.FloatTpe => ClassTag.Float.asInstanceOf[ClassTag[T]]
- case rm.DoubleTpe => ClassTag.Double.asInstanceOf[ClassTag[T]]
- case rm.BooleanTpe => ClassTag.Boolean.asInstanceOf[ClassTag[T]]
- case rm.UnitTpe => ClassTag.Unit.asInstanceOf[ClassTag[T]]
- case rm.AnyTpe => ClassTag.Any.asInstanceOf[ClassTag[T]]
- case rm.ObjectTpe => ClassTag.Object.asInstanceOf[ClassTag[T]]
- case rm.AnyValTpe => ClassTag.AnyVal.asInstanceOf[ClassTag[T]]
- case rm.AnyRefTpe => ClassTag.AnyRef.asInstanceOf[ClassTag[T]]
- case rm.NothingTpe => ClassTag.Nothing.asInstanceOf[ClassTag[T]]
- case rm.NullTpe => ClassTag.Null.asInstanceOf[ClassTag[T]]
- case rm.StringTpe => ClassTag.String.asInstanceOf[ClassTag[T]]
- case _ => apply[T](rm.typeToClass(tpe.erasure))
+ case _ => new ClassTag[T]{ def erasure = erasure1 }
}
- def apply[T](ttag: rm.ConcreteTypeTag[T]): ClassTag[T] =
- if (ttag.erasure != null) ClassTag[T](ttag.erasure)
- else ClassTag[T](ttag.tpe)
-
- implicit def toDeprecatedClassManifestApis[T](ctag: ClassTag[T]): DeprecatedClassManifestApis[T] = new DeprecatedClassManifestApis[T](ctag)
-
- @deprecated("Use apply instead", "2.10.0")
- def fromClass[T](clazz: jClass[T]): ClassManifest[T] = apply(clazz)
-
- /** Manifest for the singleton type `value.type'. */
- @deprecated("Manifests aka type tags now support arbitrary types. Build a manifest directly from the type instead", "2.10.0")
- def singleType[T <: AnyRef](value: AnyRef): Manifest[T] = ???
-
- /** ClassManifest for the class type `clazz', where `clazz' is
- * a top-level or static class.
- * @note This no-prefix, no-arguments case is separate because we
- * it's called from ScalaRunTime.boxArray itself. If we
- * pass varargs as arrays into this, we get an infinitely recursive call
- * to boxArray. (Besides, having a separate case is more efficient)
- */
- @deprecated("Manifests aka type tags now support arbitrary types. Build a manifest directly from the type instead", "2.10.0")
- def classType[T <: AnyRef](clazz: jClass[_]): ClassManifest[T] = ClassTag[T](clazz)
-
- /** ClassManifest for the class type `clazz[args]', where `clazz' is
- * a top-level or static class and `args` are its type arguments */
- @deprecated("Manifests aka type tags now support arbitrary types. Build a manifest directly from the type instead", "2.10.0")
- def classType[T <: AnyRef](clazz: jClass[_], arg1: OptManifest[_], args: OptManifest[_]*): ClassManifest[T] = ClassTag[T](clazz)
-
- /** ClassManifest for the class type `clazz[args]', where `clazz' is
- * a class with non-package prefix type `prefix` and type arguments `args`.
- */
- @deprecated("Manifests aka type tags now support arbitrary types. Build a manifest directly from the type instead", "2.10.0")
- def classType[T <: AnyRef](prefix: OptManifest[_], clazz: jClass[_], args: OptManifest[_]*): ClassManifest[T] = ClassTag[T](clazz)
-
- @deprecated("Manifests aka type tags now support arbitrary types. Build a manifest directly from the type instead", "2.10.0")
- def arrayType[T](arg: OptManifest[_]): ClassManifest[Array[T]] = arg match {
- case x: ConcreteTypeTag[_] => ClassManifest[Array[T]](x.erasure)
- case _ => Object.asInstanceOf[ClassManifest[Array[T]]] // was there in 2.9.x
- }
-
- /** ClassManifest 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. */
- @deprecated("Manifests aka type tags now support arbitrary types. Build a manifest directly from the type instead", "2.10.0")
- def abstractType[T](prefix: OptManifest[_], name: String, clazz: jClass[_], args: OptManifest[_]*): ClassManifest[T] = ClassTag[T](clazz)
-
- /** ClassManifest 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.
- * todo: remove after next boostrap
- */
- @deprecated("Manifests aka type tags now support arbitrary types. Build a manifest directly from the type instead", "2.10.0")
- def abstractType[T](prefix: OptManifest[_], name: String, upperbound: ClassManifest[_], args: OptManifest[_]*): ClassManifest[T] = ClassTag[T](upperbound.erasure)
-
- class DeprecatedClassManifestApis[T](ctag: ClassTag[T]) {
- import scala.collection.mutable.{ WrappedArray, ArrayBuilder }
-
- @deprecated("Use `tpe` to analyze the underlying type", "2.10.0")
- def <:<(that: ClassManifest[_]): Boolean = ctag.tpe <:< that.tpe
-
- @deprecated("Use `tpe` to analyze the underlying type", "2.10.0")
- def >:>(that: ClassManifest[_]): Boolean = that <:< ctag
-
- @deprecated("Use `wrap` instead", "2.10.0")
- def arrayManifest: ClassManifest[Array[T]] = ctag.wrap
-
- @deprecated("Use a combination of `wrap` and `newArray` instead", "2.10.0")
- def newArray2(len: Int): Array[Array[T]] = ctag.wrap.newArray(len)
-
- @deprecated("Use a combination of `wrap` and `newArray` instead", "2.10.0")
- def newArray3(len: Int): Array[Array[Array[T]]] = ctag.wrap.wrap.newArray(len)
-
- @deprecated("Use a combination of `wrap` and `newArray` instead", "2.10.0")
- def newArray4(len: Int): Array[Array[Array[Array[T]]]] = ctag.wrap.wrap.wrap.newArray(len)
-
- @deprecated("Use a combination of `wrap` and `newArray` instead", "2.10.0")
- def newArray5(len: Int): Array[Array[Array[Array[Array[T]]]]] = ctag.wrap.wrap.wrap.wrap.newArray(len)
-
- @deprecated("Use `@scala.collection.mutable.WrappedArray` object instead", "2.10.0")
- def newWrappedArray(len: Int): WrappedArray[T] =
- ctag.erasure match {
- case java.lang.Byte.TYPE => new WrappedArray.ofByte(new Array[Byte](len)).asInstanceOf[WrappedArray[T]]
- case java.lang.Short.TYPE => new WrappedArray.ofShort(new Array[Short](len)).asInstanceOf[WrappedArray[T]]
- case java.lang.Character.TYPE => new WrappedArray.ofChar(new Array[Char](len)).asInstanceOf[WrappedArray[T]]
- case java.lang.Integer.TYPE => new WrappedArray.ofInt(new Array[Int](len)).asInstanceOf[WrappedArray[T]]
- case java.lang.Long.TYPE => new WrappedArray.ofLong(new Array[Long](len)).asInstanceOf[WrappedArray[T]]
- case java.lang.Float.TYPE => new WrappedArray.ofFloat(new Array[Float](len)).asInstanceOf[WrappedArray[T]]
- case java.lang.Double.TYPE => new WrappedArray.ofDouble(new Array[Double](len)).asInstanceOf[WrappedArray[T]]
- case java.lang.Boolean.TYPE => new WrappedArray.ofBoolean(new Array[Boolean](len)).asInstanceOf[WrappedArray[T]]
- case java.lang.Void.TYPE => new WrappedArray.ofUnit(new Array[Unit](len)).asInstanceOf[WrappedArray[T]]
- case _ => new WrappedArray.ofRef[T with AnyRef](ctag.newArray(len).asInstanceOf[Array[T with AnyRef]]).asInstanceOf[WrappedArray[T]]
- }
-
- @deprecated("Use `@scala.collection.mutable.ArrayBuilder` object instead", "2.10.0")
- def newArrayBuilder(): ArrayBuilder[T] = ArrayBuilder.make[T]()(ctag)
-
- @deprecated("`typeArguments` is no longer supported, and will always return an empty list. Use `@scala.reflect.TypeTag` or `@scala.reflect.ConcreteTypeTag` to capture and analyze type arguments", "2.10.0")
- def typeArguments: List[OptManifest[_]] = List()
- }
-}
-
+ def unapply[T](ctag: ClassTag[T]): Option[Class[_]] = Some(ctag.erasure)
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/DummyMirror.scala b/src/library/scala/reflect/DummyMirror.scala
index dd4791e57c..8b2ddde2a1 100644
--- a/src/library/scala/reflect/DummyMirror.scala
+++ b/src/library/scala/reflect/DummyMirror.scala
@@ -430,6 +430,8 @@ class DummyMirror(cl: ClassLoader) extends api.Mirror {
def fullName: String = notSupported()
def id: Int = notSupported()
def orElse[T](alt: => Symbol): Symbol = notSupported()
+ def filter(cond: Symbol => Boolean): Symbol = notSupported()
+ def suchThat(cond: Symbol => Boolean): Symbol = notSupported()
def privateWithin: Symbol = notSupported()
def companionSymbol: Symbol = notSupported()
def moduleClass: Symbol = notSupported()
diff --git a/src/library/scala/reflect/ErasureTag.scala b/src/library/scala/reflect/ErasureTag.scala
new file mode 100644
index 0000000000..f95451fab2
--- /dev/null
+++ b/src/library/scala/reflect/ErasureTag.scala
@@ -0,0 +1,23 @@
+package scala.reflect
+
+import java.lang.{Class => jClass}
+
+/** An `ErasureTag[T]` is a descriptor that is requested by the compiler every time
+ * when it needs to persist an erasure of a type.
+ *
+ * Scala library provides a standard implementation of this trait,
+ * `TypeTag[T]` that carries the `java.lang.Class` erasure for arbitrary types.
+ *
+ * However other platforms may reimplement this trait as they see fit
+ * and then expose the implementation via an implicit macro.
+ *
+ * If you need to guarantee that the type does not contain
+ * references to type parameters or abstract types, use `ClassTag[T]`.
+ *
+ * @see [[scala.reflect.api.TypeTags]]
+ */
+@annotation.implicitNotFound(msg = "No ErasureTag available for ${T}")
+trait ErasureTag[T] {
+ /** Returns an erasure of type `T` */
+ def erasure: jClass[_]
+}
diff --git a/src/library/scala/reflect/ReflectionUtils.scala b/src/library/scala/reflect/ReflectionUtils.scala
index 79a42f6ec4..6ea69cb80d 100644
--- a/src/library/scala/reflect/ReflectionUtils.scala
+++ b/src/library/scala/reflect/ReflectionUtils.scala
@@ -5,6 +5,7 @@
package scala.reflect
+import java.lang.{Class => jClass}
import java.lang.reflect.{ InvocationTargetException, UndeclaredThrowableException }
/** A few java-reflection oriented utility functions useful during reflection bootstrapping.
diff --git a/src/library/scala/reflect/TagMaterialization.scala b/src/library/scala/reflect/TagMaterialization.scala
deleted file mode 100644
index e8d4571228..0000000000
--- a/src/library/scala/reflect/TagMaterialization.scala
+++ /dev/null
@@ -1,122 +0,0 @@
-package scala.reflect
-
-import api.Universe
-import makro.Context
-import language.implicitConversions
-
-// todo. unfortunately, current type inferencer doesn't infer type parameters of implicit values
-// this means that during macro expansion these macros will get Nothing instead of real T
-// Oh how much I'd love to implement this now, but I have to postpone this until we have a solution for type inference
-
-/** This object is required by the compiler and <b>should not be used in client code</b>. */
-
- /** !!! Some of this code is copy-pasted four places. This situation
- * should be resolved ASAP.
- */
-object TagMaterialization {
- def materializeClassTag[T: c.TypeTag](c: Context): c.Expr[ClassTag[T]] = {
- import c.mirror._
- val tpe = implicitly[c.TypeTag[T]].tpe
- c.materializeClassTag(tpe)
- }
-
- def materializeTypeTag[T: c.TypeTag](c: Context { type PrefixType = Universe }): c.Expr[c.prefix.value.TypeTag[T]] = {
- import c.mirror._
- val tpe = implicitly[c.TypeTag[T]].tpe
- c.materializeTypeTag(tpe, requireConcreteTypeTag = false)
- }
-
- def materializeConcreteTypeTag[T: c.TypeTag](c: Context { type PrefixType = Universe }): c.Expr[c.prefix.value.ConcreteTypeTag[T]] = {
- import c.mirror._
- val tpe = implicitly[c.TypeTag[T]].tpe
- c.materializeTypeTag(tpe, requireConcreteTypeTag = true)
- }
-
- private implicit def context2utils(c0: Context) : Utils { val c: c0.type } = new { val c: c0.type = c0 } with Utils
-
- private abstract class Utils {
- val c: Context
-
- import c.mirror._
- import definitions._
-
- val coreTags = Map(
- ByteClass.asType -> newTermName("Byte"),
- ShortClass.asType -> newTermName("Short"),
- CharClass.asType -> newTermName("Char"),
- IntClass.asType -> newTermName("Int"),
- LongClass.asType -> newTermName("Long"),
- FloatClass.asType -> newTermName("Float"),
- DoubleClass.asType -> newTermName("Double"),
- BooleanClass.asType -> newTermName("Boolean"),
- UnitClass.asType -> newTermName("Unit"),
- AnyClass.asType -> newTermName("Any"),
- ObjectClass.asType -> newTermName("Object"),
- AnyValClass.asType -> newTermName("AnyVal"),
- AnyRefClass.asType -> newTermName("AnyRef"),
- NothingClass.asType -> newTermName("Nothing"),
- NullClass.asType -> newTermName("Null"))
-
- val ReflectPackage = staticModule("scala.reflect.package")
- val Reflect_mirror = selectTerm(ReflectPackage, "mirror")
- val ClassTagClass = staticClass("scala.reflect.ClassTag")
- val ClassTagErasure = selectTerm(ClassTagClass, "erasure")
- val ClassTagModule = staticModule("scala.reflect.ClassTag")
- val TypeTagsClass = staticClass("scala.reflect.api.TypeTags")
- val TypeTagClass = selectType(TypeTagsClass, "TypeTag")
- val TypeTagTpe = selectTerm(TypeTagClass, "tpe")
- val TypeTagModule = selectTerm(TypeTagsClass, "TypeTag")
- val ConcreteTypeTagClass = selectType(TypeTagsClass, "ConcreteTypeTag")
- val ConcreteTypeTagModule = selectTerm(TypeTagsClass, "ConcreteTypeTag")
-
- def materializeClassTag(tpe: Type): Tree =
- materializeTag(c.reflectMirrorPrefix, tpe, ClassTagModule, c.reifyErasure(tpe))
-
- def materializeTypeTag(tpe: Type, requireConcreteTypeTag: Boolean): Tree = {
- def prefix: Tree = ??? // todo. needs to be synthesized from c.prefix
- val tagModule = if (requireConcreteTypeTag) ConcreteTypeTagModule else TypeTagModule
- materializeTag(prefix, tpe, tagModule, c.reifyType(prefix, tpe, dontSpliceAtTopLevel = true, requireConcreteTypeTag = requireConcreteTypeTag))
- }
-
- private def materializeTag(prefix: Tree, tpe: Type, tagModule: Symbol, materializer: => Tree): Tree = {
- val result =
- tpe match {
- case coreTpe if coreTags contains coreTpe =>
- Select(Select(prefix, tagModule.name), coreTags(coreTpe))
- case _ =>
- try materializer
- catch {
- case ex: Throwable =>
- // [Eugene] cannot pattern match on an abstract type, so had to do this
- val ex1 = ex
- if (ex.getClass.toString.endsWith("$ReificationError")) {
- ex match {
- case c.ReificationError(pos, msg) =>
- c.error(pos, msg)
- EmptyTree
- }
- } else if (ex.getClass.toString.endsWith("$UnexpectedReificationError")) {
- ex match {
- case c.UnexpectedReificationError(pos, err, cause) =>
- if (cause != null) throw cause else throw ex
- }
- } else {
- throw ex
- }
- }
- }
- try c.typeCheck(result)
- catch { case terr @ c.TypeError(pos, msg) => fail(terr) }
- }
-
- private def fail(reason: Any): Nothing = {
- val Apply(TypeApply(fun, List(tpeTree)), _) = c.macroApplication
- val tpe = tpeTree.tpe
- val PolyType(_, MethodType(_, tagTpe)) = fun.tpe
- val tagModule = tagTpe.typeSymbol.companionSymbol
- if (c.compilerSettings.contains("-Xlog-implicits"))
- c.echo(c.enclosingPosition, "cannot materialize " + tagModule.name + "[" + tpe + "] because:\n" + reason)
- c.abort(c.enclosingPosition, "No %s available for %s".format(tagModule.name, tpe))
- }
- }
-}
diff --git a/src/library/scala/reflect/api/Symbols.scala b/src/library/scala/reflect/api/Symbols.scala
index 767246a294..dbd264c0ab 100755
--- a/src/library/scala/reflect/api/Symbols.scala
+++ b/src/library/scala/reflect/api/Symbols.scala
@@ -148,6 +148,14 @@ trait Symbols { self: Universe =>
*/
def orElse[T](alt: => Symbol): Symbol
+ /** ...
+ */
+ def filter(cond: Symbol => Boolean): Symbol
+
+ /** ...
+ */
+ def suchThat(cond: Symbol => Boolean): Symbol
+
/**
* Set when symbol has a modifier of the form private[X], NoSymbol otherwise.
*
diff --git a/src/library/scala/reflect/api/TypeTags.scala b/src/library/scala/reflect/api/TypeTags.scala
index b90475b15a..c58b0fcec2 100644
--- a/src/library/scala/reflect/api/TypeTags.scala
+++ b/src/library/scala/reflect/api/TypeTags.scala
@@ -6,7 +6,6 @@
package scala.reflect
package api
-import scala.reflect.{ mirror => rm }
import java.lang.{ Class => jClass }
import language.implicitConversions
@@ -15,22 +14,41 @@ import language.implicitConversions
* They are supposed to replace the pre-2.10 concept of a [[scala.reflect.Manifest]].
* TypeTags are much better integrated with reflection than manifests are, and are consequently much simpler.
*
- * Type tags are organized in a hierarchy of two classes:
+ * === Overview ===
+ *
+ * Type tags are organized in a hierarchy of five classes:
+ * [[scala.reflect.ArrayTag]], [[scala.reflect.ErasureTag]], [[scala.reflect.ClassTag]],
* [[scala.reflect.api.Universe#TypeTag]] and [[scala.reflect.api.Universe#ConcreteTypeTag]].
- * A [[scala.reflect.api.Universe#TypeTag]] value wraps a full Scala type in its tpe field.
- * A [[scala.reflect.api.Universe#ConcreteTypeTag]] value is a type tag that is guaranteed not to contain any references to type parameters or abstract types.
*
- * It is also possible to capture Java classes by using a different kind of tag.
- * A [[scala.reflect.ClassTag]] value wraps a Java class, which can be accessed via the erasure method.
+ * An [[scala.reflect.ArrayTag]] value carries knowledge about how to build an array of elements of type T.
+ * Typically such operation is performed by storing an erasure and instantiating arrays via Java reflection,
+ * but [[scala.reflect.ArrayTag]] only defines an interface, not an implementation, hence it only contains the factory methods
+ * `newArray` and `wrap` that can be used to build, correspondingly, single-dimensional and multi-dimensional arrays.
*
- * TypeTags correspond loosely to Manifests. More precisely:
- * The previous notion of a [[scala.reflect.ClassManifest]] corresponds to a scala.reflect.ClassTag,
- * The previous notion of a [[scala.reflect.Manifest]] corresponds to scala.reflect.mirror.ConcreteTypeTag,
- * Whereas scala.reflect.mirror.TypeTag is approximated by the previous notion of [[scala.reflect.OptManifest]].
+ * An [[scala.reflect.ErasureTag]] value wraps a Java class, which can be accessed via the `erasure` method.
+ * This notion, previously embodied in a [[scala.reflect.ClassManifest]] together with the notion of array creation,
+ * deserves a concept of itself. Quite often (e.g. for serialization or classloader introspection) it's useful to
+ * know an erasure, and only it, so we've implemented this notion in [[scala.reflect.ErasureTag]].
*
- * Implicit in the contract for all Tag classes is that the reified type tpe represents the type parameter T.
- * Tags are typically created by the compiler, which makes sure that this contract is kept.
+ * A [[scala.reflect.ClassTag]] is a standard implementation of both [[scala.reflect.ArrayTag]] and [[scala.reflect.ErasureTag]].
+ * It guarantees that the source type T did not to contain any references to type parameters or abstract types.
+ * [[scala.reflect.ClassTag]] corresponds to a previous notion of [[scala.reflect.ClassManifest]].
*
+ * A [[scala.reflect.api.Universe#TypeTag]] value wraps a full Scala type in its tpe field.
+ * A [[scala.reflect.api.Universe#ConcreteTypeTag]] value is a [[scala.reflect.api.Universe#TypeTag]]
+ * that is guaranteed not to contain any references to type parameters or abstract types.
+ * Both flavors of TypeTags also carry an erasure, so [[scala.reflect.api.Universe#TypeTag]] is also an [[scala.reflect.ErasureTag]],
+ * and [[scala.reflect.api.Universe#ConcreteTypeTag]] is additionally an [[scala.reflect.ArrayTag]] and a [[scala.reflect.ClassTag]]
+ *
+ * It is recommended to use the tag supertypes of to precisely express your intent, i.e.:
+ * use ArrayTag when you want to construct arrays,
+ * use ErasureTag when you need an erasure and don't mind it being generated for untagged abstract types,
+ * use ClassTag only when you need an erasure of a type that doesn't refer to untagged abstract types.
+ *
+ * === Splicing ===
+ *
+ * Tags can be spliced, i.e. if compiler generates a tag for a type that contains references to tagged
+ * type parameters or abstract type members, it will retrieve the corresponding tag and embed it into the result.
* An example that illustrates the TypeTag embedding, consider the following function:
*
* import reflect.mirror._
@@ -44,6 +62,54 @@ import language.implicitConversions
* TypeTag(<[ String => U ]>).
*
* Note that T has been replaced by String, because it comes with a TypeTag in f, whereas U was left as a type parameter.
+ *
+ * === ErasureTag vs ClassTag and TypeTag vs ConcreteTypeTag ===
+ *
+ * Be careful with ErasureTag and TypeTag, because they will reify types even if these types are abstract.
+ * This makes it easy to forget to tag one of the methods in the call chain and discover it much later in the runtime
+ * by getting cryptic errors far away from their source. For example, consider the following snippet:
+ *
+ * def bind[T: TypeTag](name: String, value: T): IR.Result = bind((name, value))
+ * def bind(p: NamedParam): IR.Result = bind(p.name, p.tpe, p.value)
+ * object NamedParam {
+ * implicit def namedValue[T: TypeTag](name: String, x: T): NamedParam = apply(name, x)
+ * def apply[T: TypeTag](name: String, x: T): NamedParam = new Typed[T](name, x)
+ * }
+ *
+ * This fragment of Scala REPL implementation defines a `bind` function that carries a named value along with its type
+ * into the heart of the REPL. Using a [[scala.reflect.api.Universe#TypeTag]] here is reasonable, because it is desirable
+ * to work with all types, even if they are type parameters or abstract type members.
+ *
+ * However if any of the three `TypeTag` context bounds is omitted, the resulting code will be incorrect,
+ * because the missing `TypeTag` will be transparently generated by the compiler, carrying meaningless information.
+ * Most likely, this problem will manifest itself elsewhere, making debugging complicated.
+ * If `TypeTag` context bounds were replaced with `ConcreteTypeTag`, then such errors would be reported statically.
+ * But in that case we wouldn't be able to use `bind` in arbitrary contexts.
+ *
+ * === Backward compatibility ===
+ *
+ * TypeTags correspond loosely to Manifests. More precisely:
+ * The previous notion of a [[scala.reflect.ClassManifest]] corresponds to a scala.reflect.ClassTag,
+ * The previous notion of a [[scala.reflect.Manifest]] corresponds to scala.reflect.mirror.ConcreteTypeTag,
+ * Whereas scala.reflect.mirror.TypeTag is approximated by the previous notion of [[scala.reflect.OptManifest]].
+ *
+ * In Scala 2.10, manifests are deprecated, so it's adviseable to migrate them to tags,
+ * because manifests might be removed in the next major release.
+ *
+ * In most cases it will be enough to replace ClassManifests with ClassTags and Manifests with ConcreteTypeTags,
+ * however there are a few caveats:
+ *
+ * 1) The notion of OptManifest is no longer supported. Tags can reify arbitrary types, so they are always available.
+ * // [Eugene] it might be useful, though, to guard against abstractness of the incoming type.
+ *
+ * 2) There's no equivalent for AnyValManifest. Consider comparing your tag with one of the core tags
+ * (defined in the corresponding companion objects) to find out whether it represents a primitive value class.
+ *
+ * 3) There's no replacement for factory methods defined in `ClassManifest` and `Manifest` companion objects.
+ * Consider assembling corresponding types using reflection API provided by Java (for classes) and Scala (for types).
+ *
+ * 4) Certain manifest functions (such as `<:<`, `>:>` and `typeArguments`) weren't included in the tag API.
+ * Consider using reflection API provided by Java (for classes) and Scala (for types) instead.
*/
trait TypeTags { self: Universe =>
@@ -56,25 +122,20 @@ trait TypeTags { self: Universe =>
* @see [[scala.reflect.api.TypeTags]]
*/
@annotation.implicitNotFound(msg = "No TypeTag available for ${T}")
- abstract case class TypeTag[T](tpe: Type) {
- // it's unsafe to use assert here, because we might run into deadlocks with Predef
- // also see comments in ClassTags.scala
- // assert(tpe != null)
-
- def sym = tpe.typeSymbol
- def isConcrete = tpe.isConcrete
- def notConcrete = !isConcrete
- def toConcrete: ConcreteTypeTag[T] = ConcreteTypeTag[T](tpe)
-
- override def toString = {
- if (!self.isInstanceOf[DummyMirror]) {
- var prefix = if (isConcrete) "ConcreteTypeTag" else "TypeTag"
- if (prefix != this.productPrefix) prefix = "*" + prefix
- prefix + "[" + tpe + "]"
- } else {
- this.productPrefix + "[?]"
- }
- }
+ trait TypeTag[T] extends ErasureTag[T] with Equals with Serializable {
+
+ def tpe: Type
+ def sym: Symbol = tpe.typeSymbol
+
+ def isConcrete: Boolean = tpe.isConcrete
+ def notConcrete: Boolean = !isConcrete
+ def toConcrete: ConcreteTypeTag[T] = ConcreteTypeTag[T](tpe, erasure)
+
+ /** case class accessories */
+ override def canEqual(x: Any) = x.isInstanceOf[TypeTag[_]]
+ override def equals(x: Any) = x.isInstanceOf[TypeTag[_]] && this.tpe == x.asInstanceOf[TypeTag[_]].tpe
+ override def hashCode = scala.runtime.ScalaRunTime.hash(tpe)
+ override def toString = if (!self.isInstanceOf[DummyMirror]) (if (isConcrete) "*ConcreteTypeTag" else "TypeTag") + "[" + tpe + "]" else "TypeTag[?]"
}
object TypeTag {
@@ -95,8 +156,10 @@ trait TypeTags { self: Universe =>
val Null : TypeTag[scala.Null] = ConcreteTypeTag.Null
val String : TypeTag[java.lang.String] = ConcreteTypeTag.String
- def apply[T](tpe: Type): TypeTag[T] =
- tpe match {
+ // todo. uncomment after I redo the starr
+ // def apply[T](tpe1: Type, erasure1: jClass[_]): TypeTag[T] =
+ def apply[T](tpe1: Type, erasure1: jClass[_]): TypeTag[T] =
+ tpe1 match {
case ByteTpe => TypeTag.Byte.asInstanceOf[TypeTag[T]]
case ShortTpe => TypeTag.Short.asInstanceOf[TypeTag[T]]
case CharTpe => TypeTag.Char.asInstanceOf[TypeTag[T]]
@@ -113,8 +176,10 @@ trait TypeTags { self: Universe =>
case NothingTpe => TypeTag.Nothing.asInstanceOf[TypeTag[T]]
case NullTpe => TypeTag.Null.asInstanceOf[TypeTag[T]]
case StringTpe => TypeTag.String.asInstanceOf[TypeTag[T]]
- case _ => new TypeTag[T](tpe) {}
+ case _ => new TypeTag[T]{ def tpe = tpe1; def erasure = erasure1 }
}
+
+ def unapply[T](ttag: TypeTag[T]): Option[Type] = Some(ttag.tpe)
}
/**
@@ -124,36 +189,40 @@ trait TypeTags { self: Universe =>
* @see [[scala.reflect.api.TypeTags]]
*/
@annotation.implicitNotFound(msg = "No ConcreteTypeTag available for ${T}")
- abstract class ConcreteTypeTag[T](tpe: Type, val erasure: jClass[_]) extends TypeTag[T](tpe) {
+ trait ConcreteTypeTag[T] extends TypeTag[T] with ClassTag[T] with Equals with Serializable {
if (!self.isInstanceOf[DummyMirror]) {
-// it's unsafe to use assert here, because we might run into deadlocks with Predef
-// also see comments in ClassTags.scala
-// assert(isConcrete, tpe)
if (notConcrete) throw new Error("%s (%s) is not concrete and cannot be used to construct a concrete type tag".format(tpe, tpe.kind))
}
- override def productPrefix = "ConcreteTypeTag"
+
+ /** case class accessories */
+ override def canEqual(x: Any) = x.isInstanceOf[TypeTag[_]] // this is done on purpose. TypeTag(tpe) and ConcreteTypeTag(tpe) should be equal if tpe's are equal
+ override def equals(x: Any) = x.isInstanceOf[TypeTag[_]] && this.tpe == x.asInstanceOf[TypeTag[_]].tpe
+ override def hashCode = scala.runtime.ScalaRunTime.hash(tpe)
+ override def toString = if (!self.isInstanceOf[DummyMirror]) "ConcreteTypeTag[" + tpe + "]" else "ConcreteTypeTag[?]"
}
object ConcreteTypeTag {
- val Byte : ConcreteTypeTag[scala.Byte] = new ConcreteTypeTag[scala.Byte](ByteTpe, ClassTag.Byte.erasure) { private def readResolve() = ConcreteTypeTag.Byte }
- val Short : ConcreteTypeTag[scala.Short] = new ConcreteTypeTag[scala.Short](ShortTpe, ClassTag.Short.erasure) { private def readResolve() = ConcreteTypeTag.Short }
- val Char : ConcreteTypeTag[scala.Char] = new ConcreteTypeTag[scala.Char](CharTpe, ClassTag.Char.erasure) { private def readResolve() = ConcreteTypeTag.Char }
- val Int : ConcreteTypeTag[scala.Int] = new ConcreteTypeTag[scala.Int](IntTpe, ClassTag.Int.erasure) { private def readResolve() = ConcreteTypeTag.Int }
- val Long : ConcreteTypeTag[scala.Long] = new ConcreteTypeTag[scala.Long](LongTpe, ClassTag.Long.erasure) { private def readResolve() = ConcreteTypeTag.Long }
- val Float : ConcreteTypeTag[scala.Float] = new ConcreteTypeTag[scala.Float](FloatTpe, ClassTag.Float.erasure) { private def readResolve() = ConcreteTypeTag.Float }
- val Double : ConcreteTypeTag[scala.Double] = new ConcreteTypeTag[scala.Double](DoubleTpe, ClassTag.Double.erasure) { private def readResolve() = ConcreteTypeTag.Double }
- val Boolean : ConcreteTypeTag[scala.Boolean] = new ConcreteTypeTag[scala.Boolean](BooleanTpe, ClassTag.Boolean.erasure) { private def readResolve() = ConcreteTypeTag.Boolean }
- val Unit : ConcreteTypeTag[scala.Unit] = new ConcreteTypeTag[scala.Unit](UnitTpe, ClassTag.Unit.erasure) { private def readResolve() = ConcreteTypeTag.Unit }
- val Any : ConcreteTypeTag[scala.Any] = new ConcreteTypeTag[scala.Any](AnyTpe, ClassTag.Any.erasure) { private def readResolve() = ConcreteTypeTag.Any }
- val Object : ConcreteTypeTag[java.lang.Object] = new ConcreteTypeTag[java.lang.Object](ObjectTpe, ClassTag.Object.erasure) { private def readResolve() = ConcreteTypeTag.Object }
- val AnyVal : ConcreteTypeTag[scala.AnyVal] = new ConcreteTypeTag[scala.AnyVal](AnyValTpe, ClassTag.AnyVal.erasure) { private def readResolve() = ConcreteTypeTag.AnyVal }
- val AnyRef : ConcreteTypeTag[scala.AnyRef] = new ConcreteTypeTag[scala.AnyRef](AnyRefTpe, ClassTag.AnyRef.erasure) { private def readResolve() = ConcreteTypeTag.AnyRef }
- val Nothing : ConcreteTypeTag[scala.Nothing] = new ConcreteTypeTag[scala.Nothing](NothingTpe, ClassTag.Nothing.erasure) { private def readResolve() = ConcreteTypeTag.Nothing }
- val Null : ConcreteTypeTag[scala.Null] = new ConcreteTypeTag[scala.Null](NullTpe, ClassTag.Null.erasure) { private def readResolve() = ConcreteTypeTag.Null }
- val String : ConcreteTypeTag[java.lang.String] = new ConcreteTypeTag[java.lang.String](StringTpe, ClassTag.String.erasure) { private def readResolve() = ConcreteTypeTag.String }
-
- def apply[T](tpe: Type, erasure: jClass[_] = null): ConcreteTypeTag[T] =
- tpe match {
+ val Byte : ConcreteTypeTag[scala.Byte] = new ConcreteTypeTag[scala.Byte]{ def tpe = ByteTpe; def erasure = ClassTag.Byte.erasure; private def readResolve() = ConcreteTypeTag.Byte }
+ val Short : ConcreteTypeTag[scala.Short] = new ConcreteTypeTag[scala.Short]{ def tpe = ShortTpe; def erasure = ClassTag.Short.erasure; private def readResolve() = ConcreteTypeTag.Short }
+ val Char : ConcreteTypeTag[scala.Char] = new ConcreteTypeTag[scala.Char]{ def tpe = CharTpe; def erasure = ClassTag.Char.erasure; private def readResolve() = ConcreteTypeTag.Char }
+ val Int : ConcreteTypeTag[scala.Int] = new ConcreteTypeTag[scala.Int]{ def tpe = IntTpe; def erasure = ClassTag.Int.erasure; private def readResolve() = ConcreteTypeTag.Int }
+ val Long : ConcreteTypeTag[scala.Long] = new ConcreteTypeTag[scala.Long]{ def tpe = LongTpe; def erasure = ClassTag.Long.erasure; private def readResolve() = ConcreteTypeTag.Long }
+ val Float : ConcreteTypeTag[scala.Float] = new ConcreteTypeTag[scala.Float]{ def tpe = FloatTpe; def erasure = ClassTag.Float.erasure; private def readResolve() = ConcreteTypeTag.Float }
+ val Double : ConcreteTypeTag[scala.Double] = new ConcreteTypeTag[scala.Double]{ def tpe = DoubleTpe; def erasure = ClassTag.Double.erasure; private def readResolve() = ConcreteTypeTag.Double }
+ val Boolean : ConcreteTypeTag[scala.Boolean] = new ConcreteTypeTag[scala.Boolean]{ def tpe = BooleanTpe; def erasure = ClassTag.Boolean.erasure; private def readResolve() = ConcreteTypeTag.Boolean }
+ val Unit : ConcreteTypeTag[scala.Unit] = new ConcreteTypeTag[scala.Unit]{ def tpe = UnitTpe; def erasure = ClassTag.Unit.erasure; private def readResolve() = ConcreteTypeTag.Unit }
+ val Any : ConcreteTypeTag[scala.Any] = new ConcreteTypeTag[scala.Any]{ def tpe = AnyTpe; def erasure = ClassTag.Any.erasure; private def readResolve() = ConcreteTypeTag.Any }
+ val Object : ConcreteTypeTag[java.lang.Object] = new ConcreteTypeTag[java.lang.Object]{ def tpe = ObjectTpe; def erasure = ClassTag.Object.erasure; private def readResolve() = ConcreteTypeTag.Object }
+ val AnyVal : ConcreteTypeTag[scala.AnyVal] = new ConcreteTypeTag[scala.AnyVal]{ def tpe = AnyValTpe; def erasure = ClassTag.AnyVal.erasure; private def readResolve() = ConcreteTypeTag.AnyVal }
+ val AnyRef : ConcreteTypeTag[scala.AnyRef] = new ConcreteTypeTag[scala.AnyRef]{ def tpe = AnyRefTpe; def erasure = ClassTag.AnyRef.erasure; private def readResolve() = ConcreteTypeTag.AnyRef }
+ val Nothing : ConcreteTypeTag[scala.Nothing] = new ConcreteTypeTag[scala.Nothing]{ def tpe = NothingTpe; def erasure = ClassTag.Nothing.erasure; private def readResolve() = ConcreteTypeTag.Nothing }
+ val Null : ConcreteTypeTag[scala.Null] = new ConcreteTypeTag[scala.Null]{ def tpe = NullTpe; def erasure = ClassTag.Null.erasure; private def readResolve() = ConcreteTypeTag.Null }
+ val String : ConcreteTypeTag[java.lang.String] = new ConcreteTypeTag[java.lang.String]{ def tpe = StringTpe; def erasure = ClassTag.String.erasure; private def readResolve() = ConcreteTypeTag.String }
+
+ // todo. uncomment after I redo the starr
+ // def apply[T](tpe1: Type, erasure1: jClass[_]): ConcreteTypeTag[T] =
+ def apply[T](tpe1: Type, erasure1: jClass[_] = null): ConcreteTypeTag[T] =
+ tpe1 match {
case ByteTpe => ConcreteTypeTag.Byte.asInstanceOf[ConcreteTypeTag[T]]
case ShortTpe => ConcreteTypeTag.Short.asInstanceOf[ConcreteTypeTag[T]]
case CharTpe => ConcreteTypeTag.Char.asInstanceOf[ConcreteTypeTag[T]]
@@ -170,69 +239,10 @@ trait TypeTags { self: Universe =>
case NothingTpe => ConcreteTypeTag.Nothing.asInstanceOf[ConcreteTypeTag[T]]
case NullTpe => ConcreteTypeTag.Null.asInstanceOf[ConcreteTypeTag[T]]
case StringTpe => ConcreteTypeTag.String.asInstanceOf[ConcreteTypeTag[T]]
- case _ => new ConcreteTypeTag[T](tpe, erasure) {}
+ case _ => new ConcreteTypeTag[T]{ def tpe = tpe1; def erasure = erasure1 }
}
def unapply[T](ttag: TypeTag[T]): Option[Type] = if (ttag.isConcrete) Some(ttag.tpe) else None
-
- implicit def toClassTag[T](ttag: rm.ConcreteTypeTag[T]): ClassTag[T] = ClassTag[T](ttag)
-
- implicit def toDeprecatedManifestApis[T](ttag: rm.ConcreteTypeTag[T]): DeprecatedManifestApis[T] = new DeprecatedManifestApis[T](ttag)
-
- // this class should not be used directly in client code
- class DeprecatedManifestApis[T](ttag: rm.ConcreteTypeTag[T]) extends ClassTag.DeprecatedClassManifestApis[T](toClassTag(ttag)) {
- @deprecated("Use `tpe` to analyze the underlying type", "2.10.0")
- def <:<(that: Manifest[_]): Boolean = ttag.tpe <:< that.tpe
-
- @deprecated("Use `tpe` to analyze the underlying type", "2.10.0")
- def >:>(that: Manifest[_]): Boolean = that <:< ttag
-
- @deprecated("Use `tpe` to analyze the type arguments", "2.10.0")
- override def typeArguments: List[Manifest[_]] = ttag.tpe.typeArguments map (targ => rm.ConcreteTypeTag(targ))
- }
-
- /** Manifest for the singleton type `value.type'. */
- @deprecated("Manifests aka type tags now support arbitrary types. Build a manifest directly from the type instead", "2.10.0")
- def singleType[T <: AnyRef](value: AnyRef): Manifest[T] = Manifest[T](???, value.getClass)
-
- /** Manifest for the class type `clazz[args]', where `clazz' is
- * a top-level or static class.
- * @note This no-prefix, no-arguments case is separate because we
- * it's called from ScalaRunTime.boxArray itself. If we
- * pass varargs as arrays into this, we get an infinitely recursive call
- * to boxArray. (Besides, having a separate case is more efficient)
- */
- @deprecated("Manifests aka type tags now support arbitrary types. Build a manifest directly from the type instead", "2.10.0")
- def classType[T](clazz: Predef.Class[_]): Manifest[T] = Manifest[T](???, clazz)
-
- /** Manifest for the class type `clazz', where `clazz' is
- * a top-level or static class and args are its type arguments. */
- @deprecated("Manifests aka type tags now support arbitrary types. Build a manifest directly from the type instead", "2.10.0")
- def classType[T](clazz: Predef.Class[T], arg1: Manifest[_], args: Manifest[_]*): Manifest[T] = Manifest[T](???, clazz)
-
- /** Manifest for the class type `clazz[args]', where `clazz' is
- * a class with non-package prefix type `prefix` and type arguments `args`.
- */
- @deprecated("Manifests aka type tags now support arbitrary types. Build a manifest directly from the type instead", "2.10.0")
- def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] = Manifest[T](???, clazz)
-
- @deprecated("Manifests aka type tags now support arbitrary types. Build a manifest directly from the type instead", "2.10.0")
- def arrayType[T](arg: Manifest[_]): Manifest[Array[T]] = Manifest[Array[T]](???, arg.asInstanceOf[Manifest[T]].arrayManifest.erasure)
-
- /** 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. */
- @deprecated("Manifests aka type tags now support arbitrary types. Build a manifest directly from the type instead", "2.10.0")
- def abstractType[T](prefix: Manifest[_], name: String, clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] = Manifest[T](???, clazz)
-
- /** Manifest for the unknown type `_ >: L <: U' in an existential.
- */
- @deprecated("Manifests aka type tags now support arbitrary types. Build a manifest directly from the type instead", "2.10.0")
- def wildcardType[T](lowerBound: Manifest[_], upperBound: Manifest[_]): Manifest[T] = Manifest[T](???, upperBound.erasure)
-
- /** Manifest for the intersection type `parents_0 with ... with parents_n'. */
- @deprecated("Manifests aka type tags now support arbitrary types. Build a manifest directly from the type instead", "2.10.0")
- def intersectionType[T](parents: Manifest[_]*): Manifest[T] = Manifest[T](???, parents.head.erasure)
}
// incantations for summoning
diff --git a/src/library/scala/reflect/api/Universe.scala b/src/library/scala/reflect/api/Universe.scala
index 2b22839d39..2a7445c41c 100755
--- a/src/library/scala/reflect/api/Universe.scala
+++ b/src/library/scala/reflect/api/Universe.scala
@@ -1,5 +1,6 @@
package scala.reflect
package api
+
import language.experimental.macros
abstract class Universe extends Symbols
@@ -65,25 +66,7 @@ abstract class Universe extends Symbols
object Universe {
def reify[T](cc: scala.reflect.makro.Context{ type PrefixType = Universe })(expr: cc.Expr[T]): cc.Expr[cc.prefix.value.Expr[T]] = {
import cc.mirror._
- try cc.reifyTree(cc.prefix, expr)
- catch {
- case ex: Throwable =>
- // [Eugene] cannot pattern match on an abstract type, so had to do this
- val ex1 = ex
- if (ex.getClass.toString.endsWith("$ReificationError")) {
- ex match {
- case cc.ReificationError(pos, msg) =>
- cc.error(pos, msg)
- EmptyTree
- }
- } else if (ex.getClass.toString.endsWith("$UnexpectedReificationError")) {
- ex match {
- case cc.UnexpectedReificationError(pos, err, cause) =>
- if (cause != null) throw cause else throw ex
- }
- } else {
- throw ex
- }
- }
+ import scala.reflect.makro.internal._
+ cc.materializeExpr(cc.prefix, expr)
}
}
diff --git a/src/library/scala/reflect/makro/Context.scala b/src/library/scala/reflect/makro/Context.scala
index b304d98a5a..668d239087 100644
--- a/src/library/scala/reflect/makro/Context.scala
+++ b/src/library/scala/reflect/makro/Context.scala
@@ -34,28 +34,11 @@ trait Context extends Aliases
object Context {
def reify[T](cc: Context{ type PrefixType = Context })(expr: cc.Expr[T]): cc.Expr[cc.prefix.value.Expr[T]] = {
import cc.mirror._
+ import scala.reflect.makro.internal._
// [Eugene] how do I typecheck this without undergoing this tiresome (and, in general, incorrect) procedure?
val prefix: Tree = Select(cc.prefix, newTermName("mirror"))
val prefixTpe = cc.typeCheck(TypeApply(Select(prefix, newTermName("asInstanceOf")), List(SingletonTypeTree(prefix)))).tpe
prefix setType prefixTpe
- try cc.reifyTree(prefix, expr)
- catch {
- case ex: Throwable =>
- // [Eugene] cannot pattern match on an abstract type, so had to do this
- if (ex.getClass.toString.endsWith("$ReificationError")) {
- ex match {
- case cc.ReificationError(pos, msg) =>
- cc.error(pos, msg)
- EmptyTree
- }
- } else if (ex.getClass.toString.endsWith("$UnexpectedReificationError")) {
- ex match {
- case cc.UnexpectedReificationError(pos, err, cause) =>
- if (cause != null) throw cause else throw ex
- }
- } else {
- throw ex
- }
- }
+ cc.materializeExpr(prefix, expr)
}
}
diff --git a/src/library/scala/reflect/makro/Reifiers.scala b/src/library/scala/reflect/makro/Reifiers.scala
index b9e82e0387..ae6669946c 100644
--- a/src/library/scala/reflect/makro/Reifiers.scala
+++ b/src/library/scala/reflect/makro/Reifiers.scala
@@ -46,11 +46,12 @@ trait Reifiers {
* The produced tree will be bound to the mirror specified by ``prefix'' (also see ``reflectMirrorPrefix'').
* For more information and examples see the documentation for ``Context.reifyTree'' and ``Universe.reify''.
*/
- def reifyType(prefix: Tree, tpe: Type, dontSpliceAtTopLevel: Boolean = false, requireConcreteTypeTag: Boolean = false): Tree
+ def reifyType(prefix: Tree, tpe: Type, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): Tree
/** Given a type, generate a tree that when compiled and executed produces the erasure of the original type.
+ * If ``concrete'' is true, then this function will bail on types, whose erasure includes abstract types (like `ClassTag` does).
*/
- def reifyErasure(tpe: Type): Tree
+ def reifyErasure(tpe: Type, concrete: Boolean = true): Tree
/** Undoes reification of a tree.
*
@@ -67,20 +68,10 @@ trait Reifiers {
* 3) compileAndEval(unreifyTree(reifyTree(tree))) ~ compileAndEval(tree) // at runtime original and unreified trees are behaviorally equivalent
*/
def unreifyTree(tree: Tree): Tree
+}
- /** Represents an error during reification
- */
- type ReificationError <: Throwable
- val ReificationError: ReificationErrorExtractor
- abstract class ReificationErrorExtractor {
- def unapply(error: ReificationError): Option[(Position, String)]
- }
+// made these guys non path-dependent, otherwise exception handling quickly becomes a mess
- /** Wraps an unexpected error during reification
- */
- type UnexpectedReificationError <: Throwable
- val UnexpectedReificationError: UnexpectedReificationErrorExtractor
- abstract class UnexpectedReificationErrorExtractor {
- def unapply(error: UnexpectedReificationError): Option[(Position, String, Throwable)]
- }
-}
+case class ReificationError(var pos: reflect.api.Position, val msg: String) extends Throwable(msg)
+
+case class UnexpectedReificationError(val pos: reflect.api.Position, val msg: String, val cause: Throwable = null) extends Throwable(msg) \ No newline at end of file
diff --git a/src/library/scala/reflect/makro/internal/Utils.scala b/src/library/scala/reflect/makro/internal/Utils.scala
index 604bba10b6..a8a2c98715 100644
--- a/src/library/scala/reflect/makro/internal/Utils.scala
+++ b/src/library/scala/reflect/makro/internal/Utils.scala
@@ -7,6 +7,20 @@ import language.experimental.macros
/** This package is required by the compiler and <b>should not be used in client code</b>. */
package object internal {
/** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeArrayTag[T](u: Universe): ArrayTag[T] = macro materializeArrayTag_impl[T]
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeArrayTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe]): c.Expr[ArrayTag[T]] =
+ c.Expr[Nothing](c.materializeArrayTag(u.tree, implicitly[c.TypeTag[T]].tpe))(c.TypeTag.Nothing)
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeErasureTag[T](u: Universe): ErasureTag[T] = macro materializeErasureTag_impl[T]
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeErasureTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe]): c.Expr[ErasureTag[T]] =
+ c.Expr[Nothing](c.materializeErasureTag(u.tree, implicitly[c.TypeTag[T]].tpe, concrete = false))(c.TypeTag.Nothing)
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
def materializeClassTag[T](u: Universe): ClassTag[T] = macro materializeClassTag_impl[T]
/** This method is required by the compiler and <b>should not be used in client code</b>. */
@@ -18,14 +32,14 @@ package object internal {
/** This method is required by the compiler and <b>should not be used in client code</b>. */
def materializeTypeTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe]): c.Expr[u.value.TypeTag[T]] =
- c.Expr[Nothing](c.materializeTypeTag(u.tree, implicitly[c.TypeTag[T]].tpe, requireConcreteTypeTag = false))(c.TypeTag.Nothing)
+ c.Expr[Nothing](c.materializeTypeTag(u.tree, implicitly[c.TypeTag[T]].tpe, concrete = false))(c.TypeTag.Nothing)
/** This method is required by the compiler and <b>should not be used in client code</b>. */
def materializeConcreteTypeTag[T](u: Universe): u.ConcreteTypeTag[T] = macro materializeConcreteTypeTag_impl[T]
/** This method is required by the compiler and <b>should not be used in client code</b>. */
def materializeConcreteTypeTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe]): c.Expr[u.value.ConcreteTypeTag[T]] =
- c.Expr[Nothing](c.materializeTypeTag(u.tree, implicitly[c.TypeTag[T]].tpe, requireConcreteTypeTag = true))(c.TypeTag.Nothing)
+ c.Expr[Nothing](c.materializeTypeTag(u.tree, implicitly[c.TypeTag[T]].tpe, concrete = true))(c.TypeTag.Nothing)
/** This method is required by the compiler and <b>should not be used in client code</b>. */
private[scala] implicit def context2utils(c0: Context) : Utils { val c: c0.type } = new { val c: c0.type = c0 } with Utils
@@ -53,14 +67,27 @@ package internal {
AnyValClass.asType -> newTermName("AnyVal"),
AnyRefClass.asType -> newTermName("AnyRef"),
NothingClass.asType -> newTermName("Nothing"),
- NullClass.asType -> newTermName("Null"))
+ NullClass.asType -> newTermName("Null"),
+ StringClass.asType -> newTermName("String"))
+
+ // todo. the following two methods won't be necessary once we implement implicit macro generators for tags
+
+ def materializeArrayTag(prefix: Tree, tpe: Type): Tree =
+ materializeClassTag(prefix, tpe)
+
+ def materializeErasureTag(prefix: Tree, tpe: Type, concrete: Boolean): Tree =
+ if (concrete) materializeClassTag(prefix, tpe) else materializeTypeTag(prefix, tpe, concrete = false)
def materializeClassTag(prefix: Tree, tpe: Type): Tree =
- materializeTag(prefix, tpe, ClassTagModule, c.reifyErasure(tpe))
+ materializeTag(prefix, tpe, ClassTagModule, {
+ val erasure = c.reifyErasure(tpe, concrete = true)
+ val factory = TypeApply(Select(Ident(ClassTagModule), "apply"), List(TypeTree(tpe)))
+ Apply(factory, List(erasure))
+ })
- def materializeTypeTag(prefix: Tree, tpe: Type, requireConcreteTypeTag: Boolean): Tree = {
- val tagModule = if (requireConcreteTypeTag) ConcreteTypeTagModule else TypeTagModule
- materializeTag(prefix, tpe, tagModule, c.reifyType(prefix, tpe, dontSpliceAtTopLevel = true, requireConcreteTypeTag = requireConcreteTypeTag))
+ def materializeTypeTag(prefix: Tree, tpe: Type, concrete: Boolean): Tree = {
+ val tagModule = if (concrete) ConcreteTypeTagModule else TypeTagModule
+ materializeTag(prefix, tpe, tagModule, c.reifyType(prefix, tpe, dontSpliceAtTopLevel = true, concrete = concrete))
}
private def materializeTag(prefix: Tree, tpe: Type, tagModule: Symbol, materializer: => Tree): Tree = {
@@ -70,32 +97,30 @@ package internal {
val ref = if (tagModule.owner.isPackageClass) Ident(tagModule) else Select(prefix, tagModule.name)
Select(ref, coreTags(coreTpe))
case _ =>
- try materializer
- catch {
- case ex: Throwable =>
- // [Eugene] cannot pattern match on an abstract type, so had to do this
- val ex1 = ex
- if (ex.getClass.toString.endsWith("$ReificationError")) {
- ex match {
- case c.ReificationError(pos, msg) =>
- c.error(pos, msg)
- EmptyTree
- }
- } else if (ex.getClass.toString.endsWith("$UnexpectedReificationError")) {
- ex match {
- case c.UnexpectedReificationError(pos, err, cause) =>
- if (cause != null) throw cause else throw ex
- }
- } else {
- throw ex
- }
- }
+ translatingReificationErrors(materializer)
}
try c.typeCheck(result)
- catch { case terr @ c.TypeError(pos, msg) => fail(terr) }
+ catch { case terr @ c.TypeError(pos, msg) => failTag(terr) }
+ }
+
+ def materializeExpr(prefix: Tree, expr: Tree): Tree = {
+ val result = translatingReificationErrors(c.reifyTree(prefix, expr))
+ try c.typeCheck(result)
+ catch { case terr @ c.TypeError(pos, msg) => failExpr(terr) }
+ }
+
+ private def translatingReificationErrors(materializer: => Tree): Tree = {
+ try materializer
+ catch {
+ case ReificationError(pos, msg) =>
+ c.error(pos.asInstanceOf[c.Position], msg) // this cast is a very small price for the sanity of exception handling
+ EmptyTree
+ case UnexpectedReificationError(pos, err, cause) if cause != null =>
+ throw cause
+ }
}
- private def fail(reason: Any): Nothing = {
+ private def failTag(reason: Any): Nothing = {
val Apply(TypeApply(fun, List(tpeTree)), _) = c.macroApplication
val tpe = tpeTree.tpe
val PolyType(_, MethodType(_, tagTpe)) = fun.tpe
@@ -104,5 +129,8 @@ package internal {
c.echo(c.enclosingPosition, "cannot materialize " + tagModule.name + "[" + tpe + "] because:\n" + reason)
c.abort(c.enclosingPosition, "No %s available for %s".format(tagModule.name, tpe))
}
+
+ private def failExpr(reason: Any): Nothing =
+ c.abort(c.enclosingPosition, "Cannot materialize Expr because:\n" + reason)
}
}
diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala
index 0958f2ce9a..640cad6c21 100644
--- a/src/library/scala/reflect/package.scala
+++ b/src/library/scala/reflect/package.scala
@@ -65,8 +65,11 @@ package object reflect {
@deprecated("Use `@scala.reflect.ConcreteTypeTag` instead", "2.10.0")
lazy val Manifest = ConcreteTypeTag
@deprecated("NoManifest is no longer supported, and using it may lead to incorrect results, Use `@scala.reflect.TypeTag` instead", "2.10.0")
- object NoManifest extends OptManifest[Nothing](scala.reflect.mirror.TypeTag.Nothing.tpe)
+ lazy val NoManifest = TypeTag.Nothing
+ // ArrayTag trait is defined separately from the mirror
+ // ErasureTag trait is defined separately from the mirror
+ // ConcreteErasureTag trait is defined separately from the mirror
// ClassTag class is defined separately from the mirror
type TypeTag[T] = scala.reflect.mirror.TypeTag[T]
type ConcreteTypeTag[T] = scala.reflect.mirror.ConcreteTypeTag[T]
diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala
index d2adc26d66..9d67644d61 100644
--- a/src/library/scala/runtime/ScalaRunTime.scala
+++ b/src/library/scala/runtime/ScalaRunTime.scala
@@ -47,12 +47,29 @@ object ScalaRunTime {
names.toSet
}
+ /** Return the class object representing an array with element class `clazz`.
+ */
+ def arrayClass(clazz: Class[_]): Class[_] = {
+ // newInstance throws an exception if the erasure is Void.TYPE. see SI-5680
+ if (clazz == java.lang.Void.TYPE) classOf[Array[Unit]]
+ else java.lang.reflect.Array.newInstance(clazz, 0).getClass
+ }
+
+ /** Return the class object representing elements in arrays described by a given schematic.
+ */
+ def arrayElementClass(schematic: Any): Class[_] = schematic match {
+ case cls: Class[_] => cls.getComponentType
+ case tag: ClassTag[_] => tag.erasure
+ case tag: ArrayTag[_] => tag.newArray(0).getClass.getComponentType
+ case _ => throw new UnsupportedOperationException("unsupported schematic %s (%s)".format(schematic, if (schematic == null) "null" else schematic.getClass))
+ }
+
/** Return the class object representing an unboxed value type,
* e.g. classOf[int], not classOf[java.lang.Integer]. The compiler
* rewrites expressions like 5.getClass to come here.
*/
- def anyValClass[T <: AnyVal : ClassManifest](value: T): Class[T] =
- classManifest[T].erasure.asInstanceOf[Class[T]]
+ def anyValClass[T <: AnyVal : ClassTag](value: T): Class[T] =
+ classTag[T].erasure.asInstanceOf[Class[T]]
/** Retrieve generic array element */
def array_apply(xs: AnyRef, idx: Int): Any = xs match {
diff --git a/src/library/scala/util/Marshal.scala b/src/library/scala/util/Marshal.scala
index c2269cde45..6eb58e8570 100644
--- a/src/library/scala/util/Marshal.scala
+++ b/src/library/scala/util/Marshal.scala
@@ -11,19 +11,19 @@
package scala.util
/**
- * Marshalling of Scala objects using Scala manifests.
+ * Marshalling of Scala objects using Scala tags.
*
* @author Stephane Micheloud
* @version 1.0
*/
object Marshal {
import java.io._
- import scala.reflect.ClassManifest
+ import scala.reflect.ClassTag
- def dump[A](o: A)(implicit m: ClassManifest[A]): Array[Byte] = {
+ def dump[A](o: A)(implicit t: ClassTag[A]): Array[Byte] = {
val ba = new ByteArrayOutputStream(512)
val out = new ObjectOutputStream(ba)
- out.writeObject(m)
+ out.writeObject(t)
out.writeObject(o)
out.close()
ba.toByteArray()
@@ -32,20 +32,20 @@ object Marshal {
@throws(classOf[IOException])
@throws(classOf[ClassCastException])
@throws(classOf[ClassNotFoundException])
- def load[A](buffer: Array[Byte])(implicit expected: ClassManifest[A]): A = {
+ def load[A](buffer: Array[Byte])(implicit expected: ClassTag[A]): A = {
val in = new ObjectInputStream(new ByteArrayInputStream(buffer))
- val found = in.readObject.asInstanceOf[ClassManifest[_]]
- // todo. [Eugene] needs review, since ClassManifests no longer capture typeArguments
- if (found.tpe <:< expected.tpe) {
- val o = in.readObject.asInstanceOf[A]
- in.close()
- o
- } else {
- in.close()
- throw new ClassCastException("type mismatch;"+
- "\n found : "+found+
- "\n required: "+expected)
+ val found = in.readObject.asInstanceOf[ClassTag[_]]
+ try {
+ // [Eugene] needs review
+ // previously was: found <:< expected
+ found.erasure.asSubclass(expected.erasure)
+ in.readObject.asInstanceOf[A]
+ } catch {
+ case _: ClassCastException =>
+ in.close()
+ throw new ClassCastException("type mismatch;"+
+ "\n found : "+found+
+ "\n required: "+expected)
}
}
-
-}
+} \ No newline at end of file