summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-08-21 13:44:04 +0000
committerMartin Odersky <odersky@gmail.com>2009-08-21 13:44:04 +0000
commit8d4c53543c38a473d9807b8217c7c5987f8bf0ec (patch)
tree4db51b23b00ca287027e18af9047c6b1e055b8f0
parent35c590828cd7265d4b9d1e5384cd87a913ebdeaa (diff)
downloadscala-8d4c53543c38a473d9807b8217c7c5987f8bf0ec.tar.gz
scala-8d4c53543c38a473d9807b8217c7c5987f8bf0ec.tar.bz2
scala-8d4c53543c38a473d9807b8217c7c5987f8bf0ec.zip
added partial manifests (now called manifests),...
added partial manifests (now called manifests), as opposed to FullManifests
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala24
-rw-r--r--src/library/scala/reflect/FullManifest.scala147
-rw-r--r--src/library/scala/reflect/Manifest.scala160
4 files changed, 206 insertions, 127 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 60b30d8a00..150cc9a12d 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -180,6 +180,8 @@ trait Definitions {
// scala.reflect
lazy val ManifestClass = getClass("scala.reflect.Manifest")
lazy val ManifestModule = getModule("scala.reflect.Manifest")
+ lazy val FullManifestClass = getClass("scala.reflect.FullManifest")
+ lazy val FullManifestModule = getModule("scala.reflect.FullManifest")
lazy val OptManifestClass = getClass("scala.reflect.OptManifest")
lazy val NoManifest = getModule("scala.reflect.NoManifest")
lazy val CodeClass = getClass(sn.Code)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 6a6c3687e0..39f4b055ad 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -578,10 +578,12 @@ self: Analyzer =>
/** The manifest corresponding to type `pt`, provided `pt` is an instance of Manifest.
*/
private def implicitManifest(pt: Type): Tree = pt match {
+ case TypeRef(_, FullManifestClass, List(arg)) =>
+ manifestOfType(arg, true)
case TypeRef(_, ManifestClass, List(arg)) =>
- manifestOfType(arg)
+ manifestOfType(arg, false)
case TypeRef(_, OptManifestClass, List(arg)) =>
- val itree = manifestOfType(arg)
+ val itree = manifestOfType(arg, false)
if (itree == EmptyTree) gen.mkAttributedRef(NoManifest) else itree
case TypeRef(_, tsym, _) if (tsym.isAbstractType) =>
implicitManifest(pt.bounds.lo)
@@ -593,7 +595,7 @@ self: Analyzer =>
* reflect.Manifest for type 'tp'. An EmptyTree is returned if
* no manifest is found. todo: make this instantiate take type params as well?
*/
- private def manifestOfType(tp: Type): Tree = {
+ private def manifestOfType(tp: Type, full: Boolean): Tree = {
/** Creates a tree that calls the factory method called constructor in object reflect.Manifest */
def manifestFactoryCall(constructor: String, args: Tree*): Tree =
@@ -602,16 +604,18 @@ self: Analyzer =>
typed { atPos(tree.pos.focus) {
Apply(
TypeApply(
- Select(gen.mkAttributedRef(ManifestModule), constructor),
+ Select(gen.mkAttributedRef(if (full) FullManifestModule else ManifestModule), constructor),
List(TypeTree(tp))
),
args.toList
)
}}
- /** Re-wraps a type in a manifest before calling inferImplicit on the result */
- def findManifest(tp: Type): Tree =
- inferImplicit(tree, appliedType(ManifestClass.typeConstructor, List(tp)), true, false, context).tree
+ /** Re-wraps a type in a manifest before calling inferImplicit on th e result */
+ def findManifest(tp: Type, manifestClass: Symbol = if (full) FullManifestClass else ManifestClass) =
+ inferImplicit(tree, appliedType(manifestClass.typeConstructor, List(tp)), true, false, context).tree
+
+ def findArgManifest(tp: Type) = findManifest(tp, if (full) FullManifestClass else OptManifestClass)
tp.normalize match {
case ThisType(_) | SingleType(_, _) =>
@@ -621,11 +625,11 @@ self: Analyzer =>
case TypeRef(pre, sym, args) =>
if (isValueClass(sym)) {
typed { atPos(tree.pos.focus) {
- Select(gen.mkAttributedRef(ManifestModule), sym.name.toString)
+ Select(gen.mkAttributedRef(FullManifestModule), sym.name.toString)
}}
}
else if (sym.isClass) {
- val suffix = gen.mkClassOf(tp) :: (args map findManifest)
+ val suffix = gen.mkClassOf(tp) :: (args map findArgManifest)
manifestFactoryCall(
"classType",
(if ((pre eq NoPrefix) || pre.typeSymbol.isStaticOwner) suffix
@@ -637,7 +641,7 @@ self: Analyzer =>
else {
manifestFactoryCall(
"abstractType",
- findManifest(pre) :: Literal(sym.name.toString) :: findManifest(tp.bounds.hi) :: (args map findManifest): _*)
+ findManifest(pre) :: Literal(sym.name.toString) :: findManifest(tp.bounds.hi) :: (args map findArgManifest): _*)
}
case RefinedType(parents, decls) =>
// refinement is not generated yet
diff --git a/src/library/scala/reflect/FullManifest.scala b/src/library/scala/reflect/FullManifest.scala
new file mode 100644
index 0000000000..ea71aedf71
--- /dev/null
+++ b/src/library/scala/reflect/FullManifest.scala
@@ -0,0 +1,147 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2007-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Manifest.scala 18506 2009-08-18 17:24:36Z odersky $
+
+
+package scala.reflect
+
+import scala.runtime._
+
+/** <p>
+ * A <code>Manifest[T]</code> is an opaque descriptor for type <code>T</code>.
+ * Currently, its only use is to give access to the erasure of the type as a
+ * <code>Class</code> instance.
+ * </p>
+ * <p>
+ * <b>BE AWARE</b>: The different type-relation operators are all forwarded
+ * to the erased type as an approximation of the final semantics where
+ * these operators should be on the unerased type.
+ * </p>
+ */
+@serializable
+trait FullManifest[T] extends Manifest[T] {
+ override def typeArguments: List[FullManifest[_]] = List()
+}
+
+/** <p>
+ * This object is used by the compiler and <b>should not be used in client
+ * code</b>. The object <code>Manifest</code> defines factory methods for
+ * manifests.
+ * </p>
+ * <p>
+ * <b>BE AWARE</b>: The factory for refinement types is missing and
+ * will be implemented in a later version of this class.
+ * </p>
+ */
+object FullManifest {
+
+ val Byte = new (FullManifest[Byte] @serializable) {
+ def erasure = java.lang.Byte.TYPE
+ override def toString = "Byte"
+ override def newArray(len: Int): BoxedArray[Byte] = new BoxedByteArray(new Array[Byte](len))
+ }
+
+ val Short = new (FullManifest[Short] @serializable) {
+ def erasure = java.lang.Short.TYPE
+ override def toString = "Short"
+ override def newArray(len: Int): BoxedArray[Short] = new BoxedShortArray(new Array[Short](len))
+ }
+
+ val Char = new (FullManifest[Char] @serializable) {
+ def erasure = java.lang.Character.TYPE
+ override def toString = "Char"
+ override def newArray(len: Int): BoxedArray[Char] = new BoxedCharArray(new Array[Char](len))
+ }
+
+ val Int = new (FullManifest[Int] @serializable) {
+ def erasure = java.lang.Integer.TYPE
+ override def toString = "Int"
+ override def newArray(len: Int): BoxedArray[Int] = new BoxedIntArray(new Array[Int](len))
+ }
+
+ val Long = new (FullManifest[Long] @serializable) {
+ def erasure = java.lang.Long.TYPE
+ override def toString = "Long"
+ override def newArray(len: Int): BoxedArray[Long] = new BoxedLongArray(new Array[Long](len))
+ }
+
+ val Float = new (FullManifest[Float] @serializable) {
+ def erasure = java.lang.Float.TYPE
+ override def toString = "Float"
+ override def newArray(len: Int): BoxedArray[Float] = new BoxedFloatArray(new Array[Float](len))
+ }
+
+ val Double = new (FullManifest[Double] @serializable) {
+ def erasure = java.lang.Double.TYPE
+ override def toString = "Double"
+ override def newArray(len: Int): BoxedArray[Double] = new BoxedDoubleArray(new Array[Double](len))
+ }
+
+ val Boolean = new (FullManifest[Boolean] @serializable) {
+ def erasure = java.lang.Boolean.TYPE
+ override def toString = "Boolean"
+ override def newArray(len: Int): BoxedArray[Boolean] = new BoxedBooleanArray(new Array[Boolean](len))
+ }
+
+ val Unit = new (FullManifest[Unit] @serializable) {
+ def erasure = java.lang.Void.TYPE
+ override def toString = "Unit"
+ override def newArray(len: Int): BoxedArray[Unit] = new BoxedUnitArray(new Array[Unit](len))
+ }
+
+ /** Manifest for the singleton type `value.type'. */
+ def singleType[T](value: Any): FullManifest[T] =
+ new (FullManifest[T] @serializable) {
+ lazy val erasure =
+ value match {
+ case anyRefValue: AnyRef => anyRefValue.getClass
+ case anyValue => error("There is no singleton type for AnyVal values")
+ }
+ override lazy val toString = value.toString + ".type"
+ }
+
+ /** Manifest for the class type `clazz', where `clazz' is
+ * a top-level or static class. */
+ def classType[T](clazz: Predef.Class[T], args: FullManifest[_]*): FullManifest[T] =
+ classType(None, clazz, args: _*)
+
+ /** Manifest for the class type `clazz[args]', where `clazz' is
+ * a top-level or static class. */
+ def classType[T](prefix: FullManifest[_], clazz: Predef.Class[_], args: FullManifest[_]*): FullManifest[T] =
+ classType(Some(prefix), clazz, args: _*)
+
+ /** Manifest for the class type `clazz[args]', where `clazz' is
+ * a top-level or static class. */
+ def classType[T](prefix: Option[FullManifest[_]], clazz: Predef.Class[_], args: FullManifest[_]*): FullManifest[T] =
+ new (FullManifest[T] @serializable) {
+ def erasure = clazz
+ override val typeArguments = args.toList
+ override def toString =
+ (if (prefix.isEmpty) "" else prefix.get.toString+"#") +
+ (if (erasure.isArray) "Array" else erasure.getName) +
+ 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: FullManifest[_], name: String, upperBound: FullManifest[_], args: FullManifest[_]*): FullManifest[T] =
+ new (FullManifest[T] @serializable) {
+ def erasure = upperBound.erasure
+ override val typeArguments = args.toList
+ override def toString = prefix.toString+"#"+name+argString
+ }
+
+ /** Manifest for the intersection type `parents_0 with ... with parents_n'. */
+ def intersectionType[T](parents: FullManifest[_]*): FullManifest[T] =
+ new (FullManifest[T] @serializable) {
+ def erasure = parents.head.erasure
+ override def toString = parents.mkString(" with ")
+ }
+}
diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala
index f5c9818b8d..6a99a2af79 100644
--- a/src/library/scala/reflect/Manifest.scala
+++ b/src/library/scala/reflect/Manifest.scala
@@ -29,7 +29,7 @@ trait Manifest[T] extends OptManifest[T] {
/** A class representing the type U to which T would be erased. Note
* that there is no subtyping relationship between T and U. */
- def erasure: Predef.Class[U] forSome { type U }
+ def erasure: Predef.Class[_]
/** Tests whether the type represented by this manifest is a subtype of
* the type represented by `that' manifest. BE AWARE: the current
@@ -43,7 +43,15 @@ trait Manifest[T] extends OptManifest[T] {
(if (subSuperClass == null) Nil else List(subSuperClass)) ::: subSuperInterfaces
(subSuper contains sup) || (subSuper exists (subtype(_, sup)))
}
- this.erasure == that.erasure || subtype(this.erasure, that.erasure)
+ def subargs(args1: List[OptManifest[_]], args2: List[OptManifest[_]]): Boolean = {
+ (args1 zip args2) forall {
+ case (x: Manifest[_], y: Manifest[_]) => x <:< y // !!! [Martin] this is wrong, need to take variance into account
+ case (NoManifest, NoManifest) => true
+ case _ => false
+ }
+ }
+ (this.erasure == that.erasure || subtype(this.erasure, that.erasure)) &&
+ subargs(this.typeArguments, that.typeArguments)
}
/** Tests whether the type represented by this manifest is a supertype
@@ -58,7 +66,7 @@ trait Manifest[T] extends OptManifest[T] {
* implementation is an approximation, as the test is done on the
* erasure of the type. */
override def equals(that: Any): Boolean = that match {
- case m:Manifest[_] => this.erasure == m.erasure
+ case m: Manifest[_] => this.erasure == m.erasure
case _ => false
}
@@ -68,7 +76,9 @@ trait Manifest[T] extends OptManifest[T] {
.asInstanceOf[BoxedArray[T]]
}
- private[reflect] def typeArguments: Option[List[Manifest[_]]] = None
+ def typeArguments: List[OptManifest[_]] = List()
+
+ protected def argString = if (typeArguments.isEmpty) "" else typeArguments.mkString("[", ", ", "]")
}
@@ -84,138 +94,54 @@ trait Manifest[T] extends OptManifest[T] {
*/
object Manifest {
- val Byte = new (Manifest[Byte] @serializable) {
- def erasure = java.lang.Byte.TYPE
- override def toString = "Byte"
- override def newArray(len: Int): BoxedArray[Byte] = new BoxedByteArray(new Array[Byte](len))
- }
-
- val Short = new (Manifest[Short] @serializable) {
- def erasure = java.lang.Short.TYPE
- override def toString = "Short"
- override def newArray(len: Int): BoxedArray[Short] = new BoxedShortArray(new Array[Short](len))
- }
-
- val Char = new (Manifest[Char] @serializable) {
- def erasure = java.lang.Character.TYPE
- override def toString = "Char"
- override def newArray(len: Int): BoxedArray[Char] = new BoxedCharArray(new Array[Char](len))
- }
-
- val Int = new (Manifest[Int] @serializable) {
- def erasure = java.lang.Integer.TYPE
- override def toString = "Int"
- override def newArray(len: Int): BoxedArray[Int] = new BoxedIntArray(new Array[Int](len))
- }
+ val Byte = FullManifest.Byte
+ val Short = FullManifest.Short
+ val Char = FullManifest.Char
+ val Int = FullManifest.Int
+ val Long = FullManifest.Long
+ val Float = FullManifest.Float
+ val Double = FullManifest.Double
+ val Boolean = FullManifest.Boolean
+ val Unit = FullManifest.Unit
- val Long = new (Manifest[Long] @serializable) {
- def erasure = java.lang.Long.TYPE
- override def toString = "Long"
- override def newArray(len: Int): BoxedArray[Long] = new BoxedLongArray(new Array[Long](len))
- }
-
- val Float = new (Manifest[Float] @serializable) {
- def erasure = java.lang.Float.TYPE
- override def toString = "Float"
- override def newArray(len: Int): BoxedArray[Float] = new BoxedFloatArray(new Array[Float](len))
- }
-
- val Double = new (Manifest[Double] @serializable) {
- def erasure = java.lang.Double.TYPE
- override def toString = "Double"
- override def newArray(len: Int): BoxedArray[Double] = new BoxedDoubleArray(new Array[Double](len))
- }
-
- val Boolean = new (Manifest[Boolean] @serializable) {
- def erasure = java.lang.Boolean.TYPE
- override def toString = "Boolean"
- override def newArray(len: Int): BoxedArray[Boolean] = new BoxedBooleanArray(new Array[Boolean](len))
- }
-
- val Unit = new (Manifest[Unit] @serializable) {
- def erasure = java.lang.Void.TYPE
- override def toString = "Unit"
- override def newArray(len: Int): BoxedArray[Unit] = new BoxedUnitArray(new Array[Unit](len))
- }
+ def singleType[T](value: Any): FullManifest[T] = FullManifest.singleType(value)
- /** Manifest for the singleton type `value.type'. */
- def singleType[T](value: Any): Manifest[T] =
- new (Manifest[T] @serializable) {
- lazy val erasure =
- value match {
- case anyRefValue: AnyRef => anyRefValue.getClass
- case anyValue => error("There is no singleton type for AnyVal values")
- }
- override lazy val toString = value.toString + ".type"
- }
+ /** Manifest for the class type `clazz[args]', where `clazz' is
+ * a top-level or static class. */
+ def classType[T](clazz: Predef.Class[_], args: OptManifest[_]*): Manifest[T] =
+ classType(None, clazz, args: _*)
- /** Manifest for the class type `clazz', where `clazz' is
+ /** Manifest for the class type `clazz[args]', where `clazz' is
* a top-level or static class. */
- def classType[T](clazz: Predef.Class[T]): Manifest[T] =
- new (Manifest[T] @serializable) {
- val erasure = clazz
- // Martin why is toString a lazy val instead of a def?
- override lazy val toString = erasure.getName
- }
+ def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: OptManifest[_]*): Manifest[T] =
+ classType(Some(prefix), clazz, args: _*)
/** Manifest for the class type `clazz[args]', where `clazz' is
* a top-level or static class. */
- def classType[T](clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
+ def classType[T](prefix: Option[Manifest[_]], clazz: Predef.Class[_], args: OptManifest[_]*): Manifest[T] =
new (Manifest[T] @serializable) {
- val erasure = clazz
- private[reflect] override val typeArguments = Some(args.toList)
- override def <:<(that: Manifest[_]): Boolean = {
- that.typeArguments match {
- case Some(thatArgs) =>
- super.<:<(that) && ((args zip thatArgs) forall { case (x, y) => x <:< y })
- case None =>
- false
- }
- }
- override lazy val toString =
+ def erasure = clazz
+ override val typeArguments = args.toList
+ override def toString =
+ (if (prefix.isEmpty) "" else prefix.get.toString+"#") +
(if (erasure.isArray) "Array" else erasure.getName) +
- args.toList.mkString("[", ", ", "]")
- }
-
- /** Manifest for the class type `prefix # clazz'. */
- def classType[T](prefix: Manifest[_], clazz: Predef.Class[_]): Manifest[T] =
- new (Manifest[T] @serializable) {
- val erasure = clazz
- override lazy val toString = prefix.toString + "#" + erasure.getName
- }
-
- /** Manifest for the class type `prefix # clazz[args]'. */
- def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
- new (Manifest[T] @serializable) {
- val erasure = clazz
- private[reflect] override val typeArguments = Some(args.toList)
- override lazy val toString =
- prefix.toString + "#" + erasure.getName + typeArguments.mkString("[", ", ", "]")
+ 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: Manifest[_]): Manifest[T] =
+ def abstractType[T](prefix: Manifest[_], name: String, upperBound: Manifest[_], args: OptManifest[_]*): Manifest[T] =
new (Manifest[T] @serializable) {
- lazy val erasure = upperBound.erasure
- override lazy val toString = prefix.toString + "#" + name
- }
-
- /** Manifest for the abstract type `prefix # name[args]'. */
- def abstractType[T](prefix: Manifest[_], name: String, upperBound: Manifest[_], args: Manifest[_]*): Manifest[T] =
- new (Manifest[T] @serializable) {
- lazy val erasure = upperBound.erasure
- private[reflect] override val typeArguments = Some(args.toList)
- override lazy val toString =
- prefix.toString + "#" + name + typeArguments.mkString("[", ", ", "]")
+ def erasure = upperBound.erasure
+ override val typeArguments = args.toList
+ override def toString = prefix.toString+"#"+name+argString
}
/** Manifest for the intersection type `parents_0 with ... with parents_n'. */
def intersectionType[T](parents: Manifest[_]*): Manifest[T] =
new (Manifest[T] @serializable) {
- lazy val erasure = parents.head.erasure
- override lazy val toString = parents.mkString(" with ")
+ def erasure = parents.head.erasure
+ override def toString = parents.mkString(" with ")
}
-
}