summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 ")
+ }
+}