diff options
-rw-r--r-- | src/library/scala/reflect/Manifest.scala | 60 | ||||
-rw-r--r-- | test/files/jvm/manifests.check | 25 | ||||
-rw-r--r-- | test/files/jvm/manifests.scala | 61 |
3 files changed, 124 insertions, 22 deletions
diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index 09a5655f27..1f5ed20432 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -1,17 +1,27 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2007-2008, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ + +// $Id$ + + package scala.reflect -/** A Manifest[T] is an opaque descriptor for type T. Currently, its only - * use is to give access to the erasure of the type as a Class instance. - * BE AWARE: 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> + * 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> + */ trait Manifest[T] { /** A class representing the type U to which T would be erased. Note @@ -51,15 +61,21 @@ trait Manifest[T] { } -/** This object is used by the compiler and <b>should not be used in - * client code</b>. The object `Manifest' defines factory methods for - * manifests. BE AWARE: The factory for refinement types is missing and - * will be implemented in a later version of this class. */ +/** <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 Manifest { /** Manifest for the singleton type `value.type'. */ def singleType[T](value: Any): Manifest[T] = - new Manifest[T] { + new Manifest[T] with java.io.Serializable { lazy val erasure = value match { case anyRefValue: AnyRef => anyRefValue.getClass @@ -71,7 +87,7 @@ object Manifest { /** Manifest for the class type `clazz', where `clazz' is * a top-level or static class. */ def classType[T](clazz: Predef.Class[T]): Manifest[T] = - new Manifest[T] { + new Manifest[T] with java.io.Serializable { val erasure = clazz override lazy val toString = erasure.getName } @@ -79,7 +95,7 @@ object Manifest { /** 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] = - new Manifest[T] { + new Manifest[T] with java.io.Serializable { val erasure = clazz val typeArguments: Seq[Manifest[_]] = args override lazy val toString = erasure.getName + typeArguments.mkString("[", ", ", "]") @@ -87,39 +103,39 @@ object Manifest { /** Manifest for the class type `prefix # clazz'. */ def classType[T](prefix: Manifest[_], clazz: Predef.Class[_]): Manifest[T] = - new Manifest[T] { + new Manifest[T] with java.io.Serializable { val erasure = clazz - override lazy val toString = prefix.toString + "#" + clazz.getName + 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] { + new Manifest[T] with java.io.Serializable { val erasure = clazz val typeArguments: Seq[Manifest[_]] = args - override lazy val toString = prefix.toString + "#" + clazz.getName + typeArguments.mkString("[", ", ", "]") + override lazy val toString = prefix.toString + "#" + erasure.getName + typeArguments.mkString("[", ", ", "]") } /** 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] = - new Manifest[T] { + new Manifest[T] with java.io.Serializable { lazy val erasure = upperBound.erasure - override lazy val toString = prefix.toString + "#" + name + 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] { + new Manifest[T] with java.io.Serializable { lazy val erasure = upperBound.erasure val typeArguments: Seq[Manifest[_]] = args - override lazy val toString = prefix.toString + "#" + name + typeArguments.mkString("[", ", ", "]") + override lazy val toString = prefix.toString + "#" + name + typeArguments.mkString("[", ", ", "]") } /** Manifest for the intersection type `parents_0 with ... with parents_n'. */ def intersectionType[T](parents: Manifest[_]*): Manifest[T] = - new Manifest[T] { + new Manifest[T] with java.io.Serializable { lazy val erasure = parents.first.erasure override lazy val toString = parents.mkString(" with ") } diff --git a/test/files/jvm/manifests.check b/test/files/jvm/manifests.check new file mode 100644 index 0000000000..a2419d2b0b --- /dev/null +++ b/test/files/jvm/manifests.check @@ -0,0 +1,25 @@ +x=(), m=java.lang.Void +x=true, m=boolean +x=a, m=char +x=1, m=int +x=abc, m=java.lang.String +x=List(()), m=scala.List[java.lang.Void] +x=List(true), m=scala.List[boolean] +x=List(1), m=scala.List[int] +x=List(abc), m=scala.List[java.lang.String] +x=[Z, m=[Z[boolean] +x=[C, m=[C[char] +x=[I, m=[I[int] +x=Array(abc), m=[Ljava.lang.String;[java.lang.String] +x=((),()), m=scala.Tuple2[java.lang.Void, java.lang.Void] +x=(true,false), m=scala.Tuple2[boolean, boolean] +x=(1,2), m=scala.Tuple2[int, int] +x=(abc,xyz), m=scala.Tuple2[java.lang.String, java.lang.String] +x=Serialize$, m=Serialize$ +x=Test$, m=Test$ +x=scala.List$, m=scala.List$ +x=Test$Foo, m=Test$Foo[int] +x=Test$Foo, m=Test$Foo[scala.List[int]] +x=Test$Foo, m=Test$Foo[Test$Foo[int]] +x=Test$Foo, m=Test$Foo[scala.List[Test$Foo[int]]] +x=Test$$anon$1, m=Test$$anon$1 diff --git a/test/files/jvm/manifests.scala b/test/files/jvm/manifests.scala new file mode 100644 index 0000000000..61c5152283 --- /dev/null +++ b/test/files/jvm/manifests.scala @@ -0,0 +1,61 @@ +object Test extends Application { + import scala.reflect._ + + def manifestOf[T](implicit m: Manifest[T]): Manifest[T] = m + + def print[T](x: T)(implicit m: Manifest[T]) { + val m1: Manifest[T] = Serialize.read(Serialize.write(m)) + val x1 = x.toString.replaceAll("@[0-9a-z]+$", "") + println("x="+x1+", m="+m1) + } + print(()) + print(true) + print('a') + print(1) + print("abc") + + print(List(())) + print(List(true)) + print(List(1)) + print(List("abc")) + + //print(Array(())) //Illegal class name "[V" in class file Test$ + print(Array(true)) + print(Array('a')) + print(Array(1)) + print(Array("abc")) + + print(((), ())) + print((true, false)) + print((1, 2)) + print(("abc", "xyz")) + + print(Serialize) + print(Test) + print(List) + + class Foo[T](x: T) + print(new Foo(2)) + print(new Foo(List(2))) + print(new Foo(new Foo(2))) + print(new Foo(List(new Foo(2)))) + + trait Bar[T] { def f: T } + print(new Bar[String] { def f = "abc" }) +} + +object Serialize { + import java.io._ + def write[A](o: A): Array[Byte] = { + val ba = new ByteArrayOutputStream(512) + val out = new ObjectOutputStream(ba) + out.writeObject(o) + out.close() + ba.toByteArray() + } + def read[A](buffer: Array[Byte]): A = { + val in = new ObjectInputStream(new ByteArrayInputStream(buffer)) + in.readObject().asInstanceOf[A] + } +} + |