summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGilles Dubochet <gilles.dubochet@epfl.ch>2008-04-24 15:52:13 +0000
committerGilles Dubochet <gilles.dubochet@epfl.ch>2008-04-24 15:52:13 +0000
commit05b846b94dc6820563e5154dd323884530f4c255 (patch)
treeb7c4a9aa74cbbc1c6ddcbdc5585867d59836c090 /src
parent04387ad63b82bf79cd89bfacdeaa9f0a2636e578 (diff)
downloadscala-05b846b94dc6820563e5154dd323884530f4c255.tar.gz
scala-05b846b94dc6820563e5154dd323884530f4c255.tar.bz2
scala-05b846b94dc6820563e5154dd323884530f4c255.zip
Manifests are generated when required by an imp...
Manifests are generated when required by an implicit. The generated Manifests are quite simple (for now) and only provide an entry point to the underlying erased type (a java.lang.Class).
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala43
-rw-r--r--src/library/scala/reflect/Manifest.scala141
3 files changed, 134 insertions, 51 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 6481bb07b9..d7ce3f22ac 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -1171,6 +1171,7 @@ trait Symbols {
* Never adds id.
*/
final def fullNameString(separator: Char): String = {
+ if (this == NoSymbol) return "<NoSymbol>"
assert(owner != NoSymbol, this)
var str =
if (owner.isRoot ||
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 481b7159f6..4f1c9e3a7e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3611,46 +3611,57 @@ trait Typers { self: Analyzer =>
tree
}
+ /** Creates a tree that calls the relevant factory method in object
+ * reflect.Manifest for type 'tp'. An EmptyTree is returned if */
def manifestOfType(pos: Position, tp: Type): Tree = {
- def mkManifest(name: String, args: Tree*): Tree =
+
+ /** Creates a tree that calls the factory method called constructor in object reflect.Manifest */
+ def manifestFactoryCall(constructor: String, args: Tree*): Tree =
if (args contains EmptyTree) EmptyTree
else
- typed {
- atPos(pos) {
- val fn = TypeApply(
- Select(gen.mkAttributedRef(ManifestModule), name),
- List(TypeTree(tp)))
- if (args.isEmpty) fn else Apply(fn, args.toList)
- }
- }
+ typed(atPos(pos) {
+ Apply(
+ TypeApply(
+ Select(gen.mkAttributedRef(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(pos, appliedType(ManifestClass.typeConstructor, List(tp)), true)
+
tp.normalize match {
case ThisType(_) | SingleType(_, _) =>
- mkManifest("singleType", gen.mkAttributedQualifier(tp))
+ manifestFactoryCall("singleType", gen.mkAttributedQualifier(tp))
case ConstantType(value) =>
findManifest(tp.deconst)
case TypeRef(pre, sym, args) =>
if (sym.isClass) {
val suffix = gen.mkClassOf(tp) :: (args map findManifest)
- mkManifest(
+ manifestFactoryCall(
"classType",
(if ((pre eq NoPrefix) || pre.typeSymbol.isStaticOwner) suffix
else findManifest(pre) :: suffix): _*)
- } else if (sym.isTypeParameterOrSkolem) {
+ }
+ else if (sym.isTypeParameterOrSkolem) {
EmptyTree // a manifest should have been found by normal searchImplicit
- } else {
- mkManifest(
+ }
+ else {
+ manifestFactoryCall(
"abstractType",
- findManifest(pre) :: Literal(sym.name.toString) :: (args map findManifest): _*)
+ findManifest(pre) :: Literal(sym.name.toString) :: findManifest(tp.bounds.hi) :: (args map findManifest): _*)
}
case RefinedType(parents, decls) =>
// refinement is not generated yet
if (parents.length == 1) findManifest(parents.head)
- else mkManifest("intersectionType", parents map findManifest: _*)
+ else manifestFactoryCall("intersectionType", parents map findManifest: _*)
case _ =>
EmptyTree
}
+
}
def applyImplicitArgs(tree: Tree): Tree = tree.tpe match {
diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala
index 14329e9526..09a5655f27 100644
--- a/src/library/scala/reflect/Manifest.scala
+++ b/src/library/scala/reflect/Manifest.scala
@@ -1,56 +1,127 @@
/* __ *\
** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
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. */
+trait Manifest[T] {
-/** This type is required by the compiler and <b>should not be used in client code</b>.
- * A Manifest[T] is a descriptor for the type T.
- * The object `Manifest' defines factory methods for manifests which still need to be implemented.
- * Also still to be done are manifests for refinement types.
- */
+ /** 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 }
+
+ /** Tests whether the type represented by this manifest is a subtype of
+ * the type represented by `that' manifest. BE AWARE: the current
+ * implementation is an approximation, as the test is done on the
+ * erasure of the type. */
+ def <:<(that: Manifest[_]): Boolean = {
+ def subtype(sub: Predef.Class[_], sup: Predef.Class[_]): Boolean = {
+ val subSuperClass = sub.getSuperclass
+ val subSuperInterfaces = sub.getInterfaces.toList
+ val subSuper =
+ (if (subSuperClass == null) Nil else List(subSuperClass)) ::: subSuperInterfaces
+ (subSuper contains sup) || (subSuper exists (subtype(_, sup)))
+ }
+ this.erasure == that.erasure || subtype(this.erasure, that.erasure)
+ }
+
+ /** Tests whether the type represented by this manifest is a supertype
+ * of the type represented by `that' manifest. BE AWARE: the current
+ * implementation is an approximation, as the test is done on the
+ * erasure of the type. */
+ def >:>(that: Manifest[_]): Boolean =
+ that <:< this
+
+ /** Tests whether the type represented by this manifest is equal to the
+ * type represented by `that' manifest. BE AWARE: the current
+ * 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 _ => false
+ }
+
+}
+
+/** 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. */
object Manifest {
- /** Manifest for the singleton type `value.type'
- */
- def singleType[T](value: Any): Manifest[T] = null
+ /** Manifest for the singleton type `value.type'. */
+ def singleType[T](value: Any): Manifest[T] =
+ new Manifest[T] {
+ 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[_]): Manifest[T] = null
+ * a top-level or static class. */
+ def classType[T](clazz: Predef.Class[T]): Manifest[T] =
+ new Manifest[T] {
+ val erasure = clazz
+ override lazy val toString = erasure.getName
+ }
/** 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] = null
-
- /** Manifest for the class type `prefix # clazz'
- */
- def classType[T](prefix: Manifest[_], clazz: Predef.Class[_]): Manifest[T] = null
+ * a top-level or static class. */
+ def classType[T](clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
+ new Manifest[T] {
+ val erasure = clazz
+ val typeArguments: Seq[Manifest[_]] = args
+ override lazy val toString = erasure.getName + typeArguments.mkString("[", ", ", "]")
+ }
- /** Manifest for the class type `prefix # clazz[args]'
- */
- def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] = null
+ /** Manifest for the class type `prefix # clazz'. */
+ def classType[T](prefix: Manifest[_], clazz: Predef.Class[_]): Manifest[T] =
+ new Manifest[T] {
+ val erasure = clazz
+ override lazy val toString = prefix.toString + "#" + clazz.getName
+ }
- /** Manifest for the abstract type `prefix # name'
- */
- def abstractType[T](prefix: Manifest[_], name: String): Manifest[T] = null
+ /** Manifest for the class type `prefix # clazz[args]'. */
+ def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
+ new Manifest[T] {
+ val erasure = clazz
+ val typeArguments: Seq[Manifest[_]] = args
+ override lazy val toString = prefix.toString + "#" + clazz.getName + typeArguments.mkString("[", ", ", "]")
+ }
- /** Manifest for the abstract type `prefix # name[args]'
- */
- def abstractType[T](prefix: Manifest[_], name: String, args: Manifest[_]*): Manifest[T] = null
+ /** 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] {
+ lazy val erasure = upperBound.erasure
+ override lazy val toString = prefix.toString + "#" + name
+ }
- /** Manifest for the intersection type `parents_0 with ... with parents_n'
- */
- def intersectionType[T](parents: Manifest[_]*): Manifest[T] = null
-}
+ /** Manifest for the abstract type `prefix # name[args]'. */
+ def abstractType[T](prefix: Manifest[_], name: String, upperBound: Manifest[_], args: Manifest[_]*): Manifest[T] =
+ new Manifest[T] {
+ lazy val erasure = upperBound.erasure
+ val typeArguments: Seq[Manifest[_]] = args
+ override lazy val toString = prefix.toString + "#" + name + typeArguments.mkString("[", ", ", "]")
+ }
-/** This type is required by the compiler and <b>should not be used in client code</b>.
- * A Manifest[T] is a descriptor for the type T. */
-abstract class Manifest[T]
+ /** Manifest for the intersection type `parents_0 with ... with parents_n'. */
+ def intersectionType[T](parents: Manifest[_]*): Manifest[T] =
+ new Manifest[T] {
+ lazy val erasure = parents.first.erasure
+ override lazy val toString = parents.mkString(" with ")
+ }
+}