From a4f1bfec2c2e1067964fad4868ae701374ab1ccd Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Wed, 9 Dec 2009 17:03:48 +0000 Subject: Took manifests a little closer to the finish line. doesn't work but the relationships between all the top, nearly top, and bottom types should all be all correct. (See lengthy test case.) --- src/library/scala/reflect/ClassManifest.scala | 19 ++++++++-- src/library/scala/reflect/Manifest.scala | 53 ++++++++++++++++----------- 2 files changed, 47 insertions(+), 25 deletions(-) (limited to 'src/library') diff --git a/src/library/scala/reflect/ClassManifest.scala b/src/library/scala/reflect/ClassManifest.scala index dd15e2f8b8..81c36fffcb 100644 --- a/src/library/scala/reflect/ClassManifest.scala +++ b/src/library/scala/reflect/ClassManifest.scala @@ -52,8 +52,18 @@ trait ClassManifest[T] extends OptManifest[T] { case _ => false } } - (this.erasure == that.erasure || subtype(this.erasure, that.erasure)) && - subargs(this.typeArguments, that.typeArguments) + + import Manifest.{ AnyVal, Nothing, Null } + + that match { + // All types which conform to AnyVal will override <:<. + case _: AnyValManifest[_] => false + // Anything which conforms to a bottom type will override <:<. + case AnyVal | Nothing | Null => false + case _ => + (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 @@ -68,7 +78,8 @@ trait ClassManifest[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: ClassManifest[_] => this.erasure == m.erasure + case _: AnyValManifest[_] => false + case m: ClassManifest[_] => this.erasure == m.erasure case _ => false } @@ -153,7 +164,7 @@ object ClassManifest { case _ => classType[T with AnyRef](clazz).asInstanceOf[ClassManifest[T]] } - def singleType[T](value: Any): Manifest[T] = Manifest.singleType(value) + def singleType[T <: AnyRef](value: AnyRef): Manifest[T] = Manifest.singleType(value) /** ClassManifest for the class type `clazz', where `clazz' is * a top-level or static class. diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index f7ed9b4be9..71324a9802 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -34,6 +34,13 @@ trait Manifest[T] extends ClassManifest[T] { Manifest.classType[Array[T]](arrayClass[T](erasure)) } +@serializable +trait AnyValManifest[T] extends Manifest[T] { + import Manifest.{ Any, AnyVal } + override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) || (that eq AnyVal) + override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] +} + /** * This object is used by the compiler and should not be used in client * code. The object Manifest defines factory methods for @@ -45,8 +52,7 @@ trait Manifest[T] extends ClassManifest[T] { *

*/ object Manifest { - - val Byte = new (Manifest[Byte] @serializable) { + val Byte = new (AnyValManifest[Byte] @serializable) { def erasure = java.lang.Byte.TYPE override def toString = "Byte" override def newArray(len: Int): Array[Byte] = new Array[Byte](len) @@ -54,7 +60,7 @@ object Manifest { override def newArrayBuilder(): ArrayBuilder[Byte] = new ArrayBuilder.ofByte() } - val Short = new (Manifest[Short] @serializable) { + val Short = new (AnyValManifest[Short] @serializable) { def erasure = java.lang.Short.TYPE override def toString = "Short" override def newArray(len: Int): Array[Short] = new Array[Short](len) @@ -62,7 +68,7 @@ object Manifest { override def newArrayBuilder(): ArrayBuilder[Short] = new ArrayBuilder.ofShort() } - val Char = new (Manifest[Char] @serializable) { + val Char = new (AnyValManifest[Char] @serializable) { def erasure = java.lang.Character.TYPE override def toString = "Char" override def newArray(len: Int): Array[Char] = new Array[Char](len) @@ -70,7 +76,7 @@ object Manifest { override def newArrayBuilder(): ArrayBuilder[Char] = new ArrayBuilder.ofChar() } - val Int = new (Manifest[Int] @serializable) { + val Int = new (AnyValManifest[Int] @serializable) { def erasure = java.lang.Integer.TYPE override def toString = "Int" override def newArray(len: Int): Array[Int] = new Array[Int](len) @@ -78,7 +84,7 @@ object Manifest { override def newArrayBuilder(): ArrayBuilder[Int] = new ArrayBuilder.ofInt() } - val Long = new (Manifest[Long] @serializable) { + val Long = new (AnyValManifest[Long] @serializable) { def erasure = java.lang.Long.TYPE override def toString = "Long" override def newArray(len: Int): Array[Long] = new Array[Long](len) @@ -86,7 +92,7 @@ object Manifest { override def newArrayBuilder(): ArrayBuilder[Long] = new ArrayBuilder.ofLong() } - val Float = new (Manifest[Float] @serializable) { + val Float = new (AnyValManifest[Float] @serializable) { def erasure = java.lang.Float.TYPE override def toString = "Float" override def newArray(len: Int): Array[Float] = new Array[Float](len) @@ -94,7 +100,7 @@ object Manifest { override def newArrayBuilder(): ArrayBuilder[Float] = new ArrayBuilder.ofFloat() } - val Double = new (Manifest[Double] @serializable) { + val Double = new (AnyValManifest[Double] @serializable) { def erasure = java.lang.Double.TYPE override def toString = "Double" override def newArray(len: Int): Array[Double] = new Array[Double](len) @@ -102,7 +108,7 @@ object Manifest { override def newArrayBuilder(): ArrayBuilder[Double] = new ArrayBuilder.ofDouble() } - val Boolean = new (Manifest[Boolean] @serializable) { + val Boolean = new (AnyValManifest[Boolean] @serializable) { def erasure = java.lang.Boolean.TYPE override def toString = "Boolean" override def newArray(len: Int): Array[Boolean] = new Array[Boolean](len) @@ -110,7 +116,7 @@ object Manifest { override def newArrayBuilder(): ArrayBuilder[Boolean] = new ArrayBuilder.ofBoolean() } - val Unit = new (Manifest[Unit] @serializable) { + val Unit = new (AnyValManifest[Unit] @serializable) { def erasure = java.lang.Void.TYPE override def toString = "Unit" override def newArray(len: Int): Array[Unit] = new Array[Unit](len) @@ -120,37 +126,42 @@ object Manifest { val Any: Manifest[Any] = new ClassTypeManifest[Any](None, classOf[java.lang.Object], List()) { override def toString = "Any" - // todo: re-implement <:< + override def <:<(that: ClassManifest[_]): Boolean = (that eq this) + override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] } val Object: Manifest[Object] = new ClassTypeManifest[Object](None, classOf[java.lang.Object], List()) { override def toString = "Object" - // todo: re-implement <:< + override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) + override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] } val AnyVal: Manifest[AnyVal] = new ClassTypeManifest[AnyVal](None, classOf[java.lang.Object], List()) { override def toString = "AnyVal" - // todo: re-implement <:< + override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) + override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] } val Null: Manifest[Null] = new ClassTypeManifest[Null](None, classOf[java.lang.Object], List()) { override def toString = "Null" - // todo: re-implement <:< + override def <:<(that: ClassManifest[_]): Boolean = + (that ne null) && (that ne Nothing) && !(that <:< AnyVal) + override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] } val Nothing: Manifest[Nothing] = new ClassTypeManifest[Nothing](None, classOf[java.lang.Object], List()) { override def toString = "Nothing" - // todo: re-implement <:< + override def <:<(that: ClassManifest[_]): Boolean = (that ne null) + override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] } /** Manifest for the singleton type `value.type'. */ - def singleType[T](value: Any): Manifest[T] = + def singleType[T <: AnyRef](value: AnyRef): 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") - } + /** Note - this was doing a type match on value to exclude AnyVal, which does not work. + * Pattern matching _: AnyRef matches everything because of boxing. + */ + lazy val erasure = value.getClass override lazy val toString = value.toString + ".type" } -- cgit v1.2.3