summaryrefslogtreecommitdiff
path: root/src/compiler/scala/reflect/internal/Definitions.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-01-30 08:05:12 -0800
committerPaul Phillips <paulp@improving.org>2012-01-30 08:21:37 -0800
commit6eb24b2beacdb2c94b7818de319b338add298c98 (patch)
tree5c8d64b5ce218ac1a47e82538412227019d85dbc /src/compiler/scala/reflect/internal/Definitions.scala
parent66b0e759258ff1185def1689bd0a1b67105922bf (diff)
downloadscala-6eb24b2beacdb2c94b7818de319b338add298c98.tar.gz
scala-6eb24b2beacdb2c94b7818de319b338add298c98.tar.bz2
scala-6eb24b2beacdb2c94b7818de319b338add298c98.zip
Moving getClassReturnType out of erasure.
And other post-merge cleanup.
Diffstat (limited to 'src/compiler/scala/reflect/internal/Definitions.scala')
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala35
1 files changed, 34 insertions, 1 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index 9c9a9293aa..4857ec6b80 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -663,7 +663,40 @@ trait Definitions extends reflect.api.StandardDefinitions {
// AnyVal_getClass is defined here. Once we have a new strap, it could also be
// defined directly in the AnyVal trait. Right now this does not work, because
// strap complains about overriding a final getClass method in Any.
- lazy val AnyVal_getClass = newMethod(AnyValClass, nme.getClass_, Nil, getClassReturnType(AnyValClass.tpe), DEFERRED)
+ lazy val AnyVal_getClass = newMethod(AnyValClass, nme.getClass_, Nil, getClassReturnType(AnyValClass.tpe))
+
+ // A type function from T => Class[U], used to determine the return
+ // type of getClass calls. The returned type is:
+ //
+ // 1. If T is a value type, Class[T].
+ // 2. If T is a phantom type (Any or AnyVal), Class[_].
+ // 3. If T is a local class, Class[_ <: |T|].
+ // 4. Otherwise, Class[_ <: T].
+ //
+ // Note: AnyVal cannot be Class[_ <: AnyVal] because if the static type of the
+ // receiver is AnyVal, it implies the receiver is boxed, so the correct
+ // class object is that of java.lang.Integer, not Int.
+ //
+ // TODO: If T is final, return type could be Class[T]. Should it?
+ def getClassReturnType(tp: Type): Type = {
+ val sym = tp.typeSymbol
+
+ if (phase.erasedTypes) ClassClass.tpe
+ else if (isValueClass(sym)) ClassType(tp.widen)
+ else {
+ val eparams = typeParamsToExistentials(ClassClass, ClassClass.typeParams)
+ val upperBound = (
+ if (isPhantomClass(sym)) AnyClass.tpe
+ else if (sym.isLocalClass) erasure.intersectionDominator(tp.parents)
+ else tp.widen
+ )
+
+ existentialAbstraction(
+ eparams,
+ ClassType(eparams.head setInfo TypeBounds.upper(upperBound) tpe)
+ )
+ }
+ }
// members of class java.lang.{ Object, String }
lazy val Object_## = newMethod(ObjectClass, nme.HASHHASH, Nil, inttype, FINAL)