aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-08-25 19:13:34 +0200
committerMartin Odersky <odersky@gmail.com>2014-08-25 22:54:06 +0200
commit97d89afc4769c4badb42284c9b5d97b663f870f6 (patch)
treed95868e077a2d701741b64be601fc53585c65493 /src/dotty/tools
parent254665e42f2a22ba271c2eb64cb8b1b06a7eaa5c (diff)
downloaddotty-97d89afc4769c4badb42284c9b5d97b663f870f6.tar.gz
dotty-97d89afc4769c4badb42284c9b5d97b663f870f6.tar.bz2
dotty-97d89afc4769c4badb42284c9b5d97b663f870f6.zip
Fixes to erasure
Makes erasure pass the test suite. Erasure is not yet turned turned on by default, because TestNonCyclic fails with a stale symbol error. The problem is that This types are coupled to Symbols and therefore don't reload. This is a problem is This types refer to static symbols that get recompiled. We either have to drop using This types for static references, or redefine thme so that can be reloaded.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/TypeErasure.scala70
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala4
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala2
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala5
-rw-r--r--src/dotty/tools/dotc/core/Types.scala26
-rw-r--r--src/dotty/tools/dotc/transform/Erasure.scala16
6 files changed, 60 insertions, 63 deletions
diff --git a/src/dotty/tools/dotc/TypeErasure.scala b/src/dotty/tools/dotc/TypeErasure.scala
index b65f2889f..c8c54ed03 100644
--- a/src/dotty/tools/dotc/TypeErasure.scala
+++ b/src/dotty/tools/dotc/TypeErasure.scala
@@ -109,6 +109,28 @@ object TypeErasure {
}
loop(tp1.baseClasses, defn.ObjectClass).typeRef
}
+
+ def erasedGlb(tp1: Type, tp2: Type, isJava: Boolean)(implicit ctx: Context): Type = tp1 match {
+ case defn.ArrayType(elem1) =>
+ tp2 match {
+ case defn.ArrayType(elem2) => defn.ArrayType(erasedGlb(elem1, elem2, isJava))
+ case _ => defn.ObjectType
+ }
+ case _ =>
+ tp2 match {
+ case defn.ArrayType(_) => defn.ObjectType
+ case _ =>
+ val tsym1 = tp1.typeSymbol
+ val tsym2 = tp2.typeSymbol
+ if (!tsym2.exists) tp1
+ else if (!tsym1.exists) tp2
+ else if (!isJava && tsym1.derivesFrom(tsym2)) tp1
+ else if (!isJava && tsym2.derivesFrom(tsym1)) tp2
+ else if (tp1.typeSymbol.isRealClass) tp1
+ else if (tp2.typeSymbol.isRealClass) tp2
+ else tp1
+ }
+ }
}
import TypeErasure._
@@ -127,15 +149,15 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
* - otherwise, if T <: Object, scala.Array+[|T|]
* - otherwise, if T is a type paramter coming from Java, scala.Array+[Object].
* - otherwise, Object
- * - 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 whose symbol is owned by Array: The typeref itself
- * - 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 term ref p.x, the type <noprefix> # x.
+ * - 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 whose symbol is owned by Array: The typeref itself, with prefix = <noprefix>
+ * - For a typeref P.C where C refers to a class, <noprefix> # 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, the merge of |T1| and |T2| (see mergeAnd)
+ * - For all other type proxies: The erasure of the underlying type.
+ * - For T1 & T2, the erased glb of |T1| and |T2| (see erasedGlb)
* - For T1 | T2, the first base class in the linearization of T which is also a base class of T2
* - For => T, ()T
* - For a method type (Fs)scala.Unit, (|Fs|)scala.Unit.
@@ -164,14 +186,12 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
case tp: TermRef =>
assert(tp.symbol.exists, tp)
TermRef(NoPrefix, tp.symbol.asTerm)
- case _: ThisType =>
- tp
case ExprType(rt) =>
MethodType(Nil, Nil, this(rt))
case tp: TypeProxy =>
this(tp.underlying)
case AndType(tp1, tp2) =>
- mergeAnd(this(tp1), this(tp2))
+ erasedGlb(this(tp1), this(tp2), isJava)
case OrType(tp1, tp2) =>
ctx.typeComparer.orType(this(tp1), this(tp2), erased = true)
case tp: MethodType =>
@@ -196,7 +216,8 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
if ((cls eq defn.ObjectClass) || cls.isPrimitiveValueClass) Nil
else if (cls eq defn.ArrayClass) defn.ObjectClass.typeRef :: Nil
else removeLaterObjects(classParents.mapConserve(eraseTypeRef))
- tp.derivedClassInfo(this(pre), parents, decls, this(tp.selfType))
+ tp.derivedClassInfo(NoPrefix, parents, decls, this(tp.selfType))
+ // can't replace selftype by NoType because this would lose the sourceModule link
}
case NoType | NoPrefix | ErrorType =>
tp
@@ -215,9 +236,8 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
unsupported("eraseDerivedValueClass")
private def eraseNormalClassRef(tref: TypeRef)(implicit ctx: Context): Type = {
- val sym = tref.symbol
- if (sym.owner is Package) normalizeClass(sym.asClass).typeRef
- else tref.derivedSelect(this(tref.prefix))
+ val cls = tref.symbol.asClass
+ (if (cls.owner is Package) normalizeClass(cls) else cls).typeRef
}
private def eraseResult(tp: Type)(implicit ctx: Context): Type = tp match {
@@ -247,28 +267,6 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
case nil => nil
}
- private def mergeAnd(tp1: Type, tp2: Type)(implicit ctx: Context): Type = tp1 match {
- case defn.ArrayType(elem1) =>
- tp2 match {
- case defn.ArrayType(elem2) => defn.ArrayType(mergeAnd(elem1, elem2))
- case _ => defn.ObjectType
- }
- case _ =>
- tp2 match {
- case defn.ArrayType(_) => defn.ObjectType
- case _ =>
- val tsym1 = tp1.typeSymbol
- val tsym2 = tp2.typeSymbol
- if (!tsym2.exists) tp1
- else if (!tsym1.exists) tp2
- else if (!isJava && tsym1.derivesFrom(tsym2)) tp1
- else if (!isJava && tsym2.derivesFrom(tsym1)) tp2
- else if (tp1.typeSymbol.isRealClass) tp1
- else if (tp2.typeSymbol.isRealClass) tp2
- else tp1
- }
- }
-
/** The name of the type as it is used in `Signature`s.
* Need to ensure correspondence with erasure!
*/
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index 9018d4015..304d9853c 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -377,9 +377,9 @@ class Definitions {
}
object ArrayType {
- def apply(elem: Type) =
+ def apply(elem: Type)(implicit ctx: Context) =
ArrayClass.typeRef.appliedTo(elem :: Nil)
- def unapply(tp: Type) = tp.dealias match {
+ def unapply(tp: Type)(implicit ctx: Context) = tp.dealias match {
case at: RefinedType if (at isRef ArrayClass) && at.argInfos.length == 1 => Some(at.argInfos.head)
case _ => None
}
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 7ba6bbec6..63ce7f756 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -922,7 +922,7 @@ object SymDenotations {
/** The type parameters of this class */
override final def typeParams(implicit ctx: Context): List[TypeSymbol] = {
def computeTypeParams = {
- if (ctx.phase.erasedTypes && (this ne defn.ArrayClass)) Nil
+ if (ctx.phase.erasedTypes && (symbol ne defn.ArrayClass)) Nil
else if (this ne initial) initial.asSymDenotation.typeParams
else decls.filter(sym =>
(sym is TypeParam) && sym.owner == symbol).asInstanceOf[List[TypeSymbol]]
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 4d818cc6f..29f6dda69 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -11,7 +11,7 @@ import printing.Disambiguation.disambiguated
import util.{Stats, DotClass, SimpleMap}
import config.Config
import config.Printers._
-import TypeErasure.erasedLub
+import TypeErasure.{erasedLub, erasedGlb}
/** Provides methods to compare types.
*/
@@ -1066,12 +1066,13 @@ class TypeComparer(initctx: Context) extends DotClass {
* Such TypeBounds can also be arbitrarily instantiated. In both cases we need to
* make sure that such types do not actually arise in source programs.
*/
- final def andType(tp1: Type, tp2: Type) = ctx.traceIndented(s"glb(${tp1.show}, ${tp2.show})", subtyping, show = true) {
+ final def andType(tp1: Type, tp2: Type, erased: Boolean = ctx.erasedTypes) = ctx.traceIndented(s"glb(${tp1.show}, ${tp2.show})", subtyping, show = true) {
val t1 = distributeAnd(tp1, tp2)
if (t1.exists) t1
else {
val t2 = distributeAnd(tp2, tp1)
if (t2.exists) t2
+ else if (erased) erasedGlb(tp1, tp2, isJava = false)
else {
//if (isHKRef(tp1)) tp2
//else if (isHKRef(tp2)) tp1
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index a8bfe61e0..e59c28ca2 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -21,7 +21,7 @@ import ast.tpd._
import ast.TreeTypeMap
import printing.Texts._
import ast.untpd
-import transform.Erasure
+import dotty.tools.dotc.transform.Erasure
import printing.Printer
import Hashable._
import Uniques._
@@ -2183,17 +2183,17 @@ object Types {
def selfType(implicit ctx: Context): Type = {
if (selfTypeCache == null) {
def fullRef = fullyAppliedRef(cls.typeRef, cls.typeParams)
- selfTypeCache =
- if (ctx.erasedTypes) fullRef
- else selfInfo match {
- case NoType =>
- fullRef
- case tp: Type =>
- if (cls is Module) tp else AndType(tp, fullRef)
- case self: Symbol =>
- assert(!(cls is Module))
- AndType(self.info, fullRef)
- }
+ def withFullRef(tp: Type): Type =
+ if (ctx.erasedTypes) fullRef else AndType(tp, fullRef)
+ selfTypeCache = selfInfo match {
+ case NoType =>
+ fullRef
+ case tp: Type =>
+ if (cls is Module) tp else withFullRef(tp)
+ case self: Symbol =>
+ assert(!(cls is Module))
+ withFullRef(self.info)
+ }
}
selfTypeCache
}
@@ -2210,7 +2210,7 @@ object Types {
}
def rebase(tp: Type)(implicit ctx: Context): Type =
- if ((prefix eq cls.owner.thisType) || !cls.owner.isClass) tp
+ if ((prefix eq cls.owner.thisType) || !cls.owner.isClass || ctx.erasedTypes) tp
else tp.substThis(cls.owner.asClass, prefix)
private var typeRefCache: Type = null
diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala
index 53e253c69..1efc6b53c 100644
--- a/src/dotty/tools/dotc/transform/Erasure.scala
+++ b/src/dotty/tools/dotc/transform/Erasure.scala
@@ -175,12 +175,13 @@ object Erasure {
* e -> unbox(e, PT) if `PT` is a primitive type and `e` is not of primitive type
* e -> cast(e, PT) otherwise
*/
- def adaptToType(tree: Tree, pt: Type)(implicit ctx: Context): Tree = {
- def makeConformant(tpw: Type): Tree = tpw match {
- case MethodType(Nil, _) =>
+ def adaptToType(tree: Tree, pt: Type)(implicit ctx: Context): Tree =
+ if (pt.isInstanceOf[FunProto]) tree
+ else tree.tpe.widen match {
+ case MethodType(Nil, _) if tree.isTerm =>
adaptToType(tree.appliedToNone, pt)
- case _ =>
- if (pt.isInstanceOf[ProtoType])
+ case tpw =>
+ if (pt.isInstanceOf[ProtoType] || tree.tpe <:< pt)
tree
else if (tpw.isErasedValueType)
adaptToType(box(tree), pt)
@@ -193,9 +194,6 @@ object Erasure {
else
cast(tree, pt)
}
- if ((pt.isInstanceOf[FunProto]) || tree.tpe <:< pt) tree
- else makeConformant(tree.tpe.widen)
- }
}
class Typer extends typer.ReTyper with NoChecking {
@@ -254,7 +252,7 @@ object Erasure {
else if (qual.tpe.derivesFrom(sym.owner) || qual.isInstanceOf[Super])
select(qual, sym)
else if (sym.owner eq defn.ArrayClass)
- selectArrayMember(qual, erasure(tree.qualifier.typeOpt.widen))
+ selectArrayMember(qual, erasure(tree.qualifier.typeOpt.widen.finalResultType))
else
recur(cast(qual, sym.owner.typeRef))
}