diff options
author | Martin Odersky <odersky@gmail.com> | 2009-08-21 13:44:04 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2009-08-21 13:44:04 +0000 |
commit | 8d4c53543c38a473d9807b8217c7c5987f8bf0ec (patch) | |
tree | 4db51b23b00ca287027e18af9047c6b1e055b8f0 /src | |
parent | 35c590828cd7265d4b9d1e5384cd87a913ebdeaa (diff) | |
download | scala-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
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Definitions.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 24 | ||||
-rw-r--r-- | src/library/scala/reflect/FullManifest.scala | 147 | ||||
-rw-r--r-- | src/library/scala/reflect/Manifest.scala | 160 |
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 ") } - } |