aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/transform/Erasure.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-02-27 09:12:27 +0100
committerMartin Odersky <odersky@gmail.com>2013-02-27 09:14:33 +0100
commit856f084c474125117ed2166720ba4192d358fbef (patch)
treebfbcc9c242dae55863ce4cd84a894fb12e34ab9f /src/dotty/tools/dotc/core/transform/Erasure.scala
parentd29cc7978daa49f68d14eba35af20fbb8dd423c1 (diff)
downloaddotty-856f084c474125117ed2166720ba4192d358fbef.tar.gz
dotty-856f084c474125117ed2166720ba4192d358fbef.tar.bz2
dotty-856f084c474125117ed2166720ba4192d358fbef.zip
Filling in all ???s
Added reporters. Added context for signatures. Implemented method signatures via erasure. Refined derivedNameType handling.
Diffstat (limited to 'src/dotty/tools/dotc/core/transform/Erasure.scala')
-rw-r--r--src/dotty/tools/dotc/core/transform/Erasure.scala96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/core/transform/Erasure.scala b/src/dotty/tools/dotc/core/transform/Erasure.scala
new file mode 100644
index 000000000..a3181a7e6
--- /dev/null
+++ b/src/dotty/tools/dotc/core/transform/Erasure.scala
@@ -0,0 +1,96 @@
+package dotty.tools.dotc
+package core
+package transform
+
+import Flags._
+import Symbols._, Types._, Contexts._
+
+object Erasure {
+
+ /** The erasure |T| of a type T. This is: !!! todo: update
+ *
+ * - 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 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.
+ * - For a typeref P.C where C refers to a nested class, |P|.C.
+ * - For a typeref P.C where C refers to an alias type, the erasure of C's alias.
+ * - For a typeref P.C where C refers to an abstract type, the erasure of C's upper bound.
+ * - For T1 & T2, erasure(T1) (??)
+ * - For T1 | T2, the first base class in the linearization of T which is also a base class of T2
+ * - For a method type (Fs)scala.Unit, (|Fs|)scala.Unit.
+ * - For any other method type (Fs)T, (|Fs|)|T|.
+ * - For a polymorphic type, the erasure of its result type.
+ * - For the class info type of java.lang.Object, the same type without any parents.
+ * - 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)
+ */
+ 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
+ else tp.derivedNamedType(erasure(tp.prefix))
+ else
+ erasure(sym.info)
+ case 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)
+ case tp: MethodType =>
+ tp.derivedMethodType(
+ tp.paramNames, tp.paramTypes.mapConserve(erasure), resultErasure(tp.resultType))
+ case tp: PolyType =>
+ erasure(tp.resultType)
+ case tp @ ClassInfo(pre, cls, classParents, decls, optSelfType) =>
+ val parents: List[TypeRef] =
+ if (cls == defn.ObjectClass || cls.isPrimitiveValueClass) Nil
+ else if (cls == defn.ArrayClass) defn.ObjectClass.typeConstructor :: Nil
+ else removeLaterObjects(classParents mapConserve (erasure(_).asInstanceOf[TypeRef]))
+ tp.derivedClassInfo(erasure(pre), parents, NoType)
+ }
+
+ def resultErasure(tp: Type)(implicit ctx: Context) =
+ if (tp.typeSymbol == defn.UnitClass) tp else erasure(tp)
+
+ def removeLaterObjects(trs: List[TypeRef])(implicit ctx: Context): List[TypeRef] = trs match {
+ case tr :: trs1 => tr :: (trs1 filter (_.typeSymbol != defn.ObjectClass))
+ case nil => nil
+ }
+}