aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/transform/Erasure.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-02-27 11:42:03 +0100
committerMartin Odersky <odersky@gmail.com>2013-02-27 11:42:03 +0100
commit5b786065301ecab3fd1b38ac9089b5d58acc9082 (patch)
tree6ad491c3ccaaff496c36a5d05297036cbef3a99f /src/dotty/tools/dotc/core/transform/Erasure.scala
parent2c8d6d37f254cfbaed8f5a87308fc25c2816d73d (diff)
downloaddotty-5b786065301ecab3fd1b38ac9089b5d58acc9082.tar.gz
dotty-5b786065301ecab3fd1b38ac9089b5d58acc9082.tar.bz2
dotty-5b786065301ecab3fd1b38ac9089b5d58acc9082.zip
Refinements to signature handling.
Decoupled paramSignature from erasure in the interest of efficiency.
Diffstat (limited to 'src/dotty/tools/dotc/core/transform/Erasure.scala')
-rw-r--r--src/dotty/tools/dotc/core/transform/Erasure.scala105
1 files changed, 69 insertions, 36 deletions
diff --git a/src/dotty/tools/dotc/core/transform/Erasure.scala b/src/dotty/tools/dotc/core/transform/Erasure.scala
index a3181a7e6..18b612536 100644
--- a/src/dotty/tools/dotc/core/transform/Erasure.scala
+++ b/src/dotty/tools/dotc/core/transform/Erasure.scala
@@ -2,19 +2,19 @@ package dotty.tools.dotc
package core
package transform
-import Flags._
-import Symbols._, Types._, Contexts._
+import Symbols._, Types._, Contexts._, Flags._, Names._
object Erasure {
- /** The erasure |T| of a type T. This is: !!! todo: update
+ /** The erasure |T| of a type T. This is:
*
- * - For a constant type, itself.
* - For a refined type scala.Array+[T]:
* - if T is Nothing or Null, scala.Array+[Object]
* - otherwise, if T <: Object, scala.Array+[|T|]
* - otherwise, if T is a type paramter coming from Java, scala.Array+[Object].
* - otherwise, Object
+ * - For a constant type, NoType or NoPrefix, the type itself.
+ * - For all other type proxies: The erasure of the underlying type.
* - For a typeref scala.Any, scala.AnyVal, scala.Singleon or scala.NotNull, java.lang.Object.
* - For a typeref scala.Unit, scala.runtime.BoxedUnit.
* - For a typeref P.C where C refers to a toplevel class, P.C.
@@ -30,49 +30,28 @@ object Erasure {
* - For a class info type of a value class, the same type without any parents.
* - For any other class info type with parents Ps, the same type with
* parents |Ps|, but with duplicate references of Object removed.
- * - for all other types, the type itself (with any sub-components erased)
+ * - For any other type, exception.
*/
def erasure(tp: Type)(implicit ctx: Context): Type = tp match {
- case ConstantType(_) =>
- tp
- case tp: RefinedType =>
- val parent = tp.parent
- if (parent.dealias.typeSymbol == defn.ArrayClass) {
- val (n, elemtp) = tp.splitArray
- if (elemtp <:< defn.NullType)
- defn.ObjectArrayType
- else if (elemtp <:< defn.ObjectType)
- (erasure(elemtp) /: (0 until n))((erased, _) =>
- defn.ArrayType.appliedTo(erased))
- else if (elemtp.typeSymbol is JavaDefined)
- defn.ObjectArrayType
- else
- defn.ObjectType
- } else erasure(parent)
case tp: TypeRef =>
val sym = tp.symbol
- if (sym == defn.AnyClass || sym == defn.AnyValClass || sym == defn.SingletonClass || sym == defn.NotNullClass)
- defn.ObjectType
- else if (sym == defn.UnitClass) defn.BoxedUnitClass.typeConstructor
- // else if (sym.isDerivedValueClass) eraseDerivedValueClassRef(tref)
- else if (sym.isClass)
- if (sym.owner.isPackage) tp
+ if (sym.isClass)
+ /*if (sym.isDerivedValueClass) eraseDerivedValueClassRef(tref)
+ else */if (sym.owner.isPackage) normalizeClass(sym.asClass).typeConstructor
else tp.derivedNamedType(erasure(tp.prefix))
- else
- erasure(sym.info)
- case NoType | NoPrefix =>
+ else erasure(sym.info)
+ case tp: RefinedType =>
+ val parent = tp.parent
+ if (parent.dealias.typeSymbol == defn.ArrayClass) eraseArray(tp)
+ else erasure(parent)
+ case ConstantType(_) | NoType | NoPrefix =>
tp
case tp: TypeProxy =>
erasure(tp.underlying)
case AndType(tp1, tp2) =>
erasure(tp1)
case OrType(tp1, tp2) =>
- var bcs1 = tp1.baseClasses
- val bc2 = tp2.baseClasses.head
- while (bcs1.nonEmpty && !bc2.isNonBottomSubClass(bcs1.head))
- bcs1 = bcs1.tail
- if (bcs1.isEmpty) defn.ObjectType
- else erasure(bcs1.head.typeConstructor)
+ erasure(tp.baseType(lubClass(tp1, tp2)))
case tp: MethodType =>
tp.derivedMethodType(
tp.paramNames, tp.paramTypes.mapConserve(erasure), resultErasure(tp.resultType))
@@ -86,6 +65,60 @@ object Erasure {
tp.derivedClassInfo(erasure(pre), parents, NoType)
}
+ def eraseArray(tp: RefinedType)(implicit ctx: Context) = {
+ val (n, elemtp) = tp.splitArray
+ if (elemtp <:< defn.NullType)
+ defn.ObjectArrayType
+ else if (elemtp <:< defn.ObjectType)
+ (erasure(elemtp) /: (0 until n))((erased, _) =>
+ defn.ArrayType.appliedTo(erased))
+ else if (elemtp.typeSymbol is JavaDefined)
+ defn.ObjectArrayType
+ else
+ defn.ObjectType
+ }
+
+ def normalizeClass(cls: ClassSymbol)(implicit ctx: Context): ClassSymbol = {
+ if (cls.owner == defn.ScalaPackageClass) {
+ if (cls == defn.AnyClass || cls == defn.AnyValClass || cls == defn.SingletonClass || cls == defn.NotNullClass)
+ return defn.ObjectClass
+ if (cls == defn.UnitClass)
+ return defn.BoxedUnitClass
+ }
+ cls
+ }
+
+ def lubClass(tp1: Type, tp2: Type)(implicit ctx: Context): ClassSymbol = {
+ var bcs1 = tp1.baseClasses
+ val bc2 = tp2.baseClasses.head
+ while (bcs1.nonEmpty && !bc2.isNonBottomSubClass(bcs1.head))
+ bcs1 = bcs1.tail
+ if (bcs1.isEmpty) defn.ObjectClass else bcs1.head
+ }
+
+ /** The parameter signature of a type.
+ * Need to ensure correspondence with erasure
+ */
+ def paramSignature(tp: Type)(implicit ctx: Context): TypeName = tp match {
+ case tp: TypeRef =>
+ val sym = tp.symbol
+ if (sym.isClass)
+ /*if (sym.isDerivedValueClass) eraseDerivedValueClassRef(tref)
+ else */if (sym.owner.isPackage) normalizeClass(sym.asClass).name
+ else sym.asClass.name
+ else paramSignature(sym.info)
+ case tp: RefinedType =>
+ val parent = tp.parent
+ if (parent.dealias.typeSymbol == defn.ArrayClass) paramSignature(eraseArray(tp))
+ else paramSignature(parent)
+ case tp: TypeProxy =>
+ paramSignature(tp.underlying)
+ case AndType(tp1, tp2) =>
+ paramSignature(tp1)
+ case OrType(tp1, tp2) =>
+ lubClass(tp1, tp2).name
+ }
+
def resultErasure(tp: Type)(implicit ctx: Context) =
if (tp.typeSymbol == defn.UnitClass) tp else erasure(tp)