aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-08-30 13:02:56 +0200
committerMartin Odersky <odersky@gmail.com>2014-08-30 13:02:56 +0200
commit4041c5d590f78323d640c6eec7e370a37a01c416 (patch)
tree15e33ffb26e1bfd4c47842670dee696c582322bf /src/dotty/tools
parent5362969b55cc73c22ea959d1960e3696a801c469 (diff)
downloaddotty-4041c5d590f78323d640c6eec7e370a37a01c416.tar.gz
dotty-4041c5d590f78323d640c6eec7e370a37a01c416.tar.bz2
dotty-4041c5d590f78323d640c6eec7e370a37a01c416.zip
Ensure that after erasure all types are erased.
Defines a predicate isErasedTypes and checks that all tree types and their widened underlying types are erased.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/TypeErasure.scala38
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala10
-rw-r--r--src/dotty/tools/dotc/core/Types.scala10
-rw-r--r--src/dotty/tools/dotc/transform/Erasure.scala3
-rw-r--r--src/dotty/tools/dotc/transform/TreeChecker.scala14
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala2
6 files changed, 57 insertions, 20 deletions
diff --git a/src/dotty/tools/dotc/TypeErasure.scala b/src/dotty/tools/dotc/TypeErasure.scala
index 63b4f396b..d2b241e71 100644
--- a/src/dotty/tools/dotc/TypeErasure.scala
+++ b/src/dotty/tools/dotc/TypeErasure.scala
@@ -1,17 +1,18 @@
package dotty.tools.dotc
package core
-import Symbols._, Types._, Contexts._, Flags._, Names._, StdNames._, Flags.JavaDefined
+import Symbols._, Types._, Contexts._, Flags._, Names._, StdNames._, Decorators._, Flags.JavaDefined
import util.DotClass
/** Erased types are:
*
- * TypeRef(NoPrefix, denot is ClassDenotation)
- * TermRef(NoPrefix, denot is SymDenotation)
+ * TypeRef(prefix is ignored, denot is ClassDenotation)
+ * TermRef(prefix is ignored, denot is SymDenotation)
* JavaArrayType
* AnnotatedType
- * MethodType ----+-- JavaMethodType
- * ClassInfo
+ * MethodType
+ * ThisType
+ * ClassInfo (NoPrefix, ...)
* NoType
* NoPrefix
* WildcardType
@@ -22,6 +23,30 @@ import util.DotClass
*/
object TypeErasure {
+ /** A predicate that tests whether a type is a legal erased type. Only asInstanceOf and
+ * isInstanceOf may have types that do not satisfy the predicate.
+ */
+ def isErasedType(tp: Type)(implicit ctx: Context): Boolean = tp match {
+ case tp: TypeRef =>
+ tp.symbol.isClass
+ case _: TermRef =>
+ true
+ case JavaArrayType(elem) =>
+ isErasedType(elem)
+ case AnnotatedType(_, tp) =>
+ isErasedType(tp)
+ case ThisType(tref) =>
+ isErasedType(tref)
+ case tp: MethodType =>
+ tp.paramTypes.forall(isErasedType) && isErasedType(tp.resultType)
+ case tp @ ClassInfo(pre, _, parents, decls, _) =>
+ isErasedType(pre) && parents.forall(isErasedType) //&& decls.forall(sym => isErasedType(sym.info)) && isErasedType(tp.selfType)
+ case NoType | NoPrefix | WildcardType | ErrorType =>
+ true
+ case _ =>
+ false
+ }
+
case class ErasedValueType(cls: ClassSymbol, underlying: Type) extends CachedGroundType {
override def computeHash = doHash(cls, underlying)
}
@@ -179,6 +204,7 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
* - 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 a this-type C.this, the type itself.
* - 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
@@ -208,6 +234,8 @@ 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 =>
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index 2c8e9902b..bf756facf 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -41,8 +41,6 @@ import TypeApplications._
/** A decorator that provides methods for modeling type application */
class TypeApplications(val self: Type) extends AnyVal {
- def canHaveTypeParams(implicit ctx: Context) = !ctx.erasedTypes || self.isRef(defn.ArrayClass)
-
/** The type parameters of this type are:
* For a ClassInfo type, the type parameters of its class.
* For a typeref referring to a class, the type parameters of the class.
@@ -187,7 +185,7 @@ class TypeApplications(val self: Type) extends AnyVal {
tp
}
- if (args.isEmpty || !canHaveTypeParams) self
+ if (args.isEmpty || ctx.erasedTypes) self
else {
val res = instantiate(self, self)
if (isInstantiatedLambda(res)) res.select(tpnme.Apply) else res
@@ -278,10 +276,8 @@ class TypeApplications(val self: Type) extends AnyVal {
*/
def translateParameterized(from: ClassSymbol, to: ClassSymbol)(implicit ctx: Context): Type =
if (self.derivesFrom(from))
- if (canHaveTypeParams)
- RefinedType(to.typeRef, to.typeParams.head.name, self.member(from.typeParams.head.name).info)
- else
- to.typeRef
+ if (ctx.erasedTypes) to.typeRef
+ else RefinedType(to.typeRef, to.typeParams.head.name, self.member(from.typeParams.head.name).info)
else self
/** If this is repeated parameter type, its underlying Seq type,
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 42ff62f4d..1cd9c4af9 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -1588,8 +1588,9 @@ object Types {
final class CachedSuperType(thistpe: Type, supertpe: Type) extends SuperType(thistpe, supertpe)
object SuperType {
- def apply(thistpe: Type, supertpe: Type)(implicit ctx: Context) =
- unique(new CachedSuperType(thistpe, supertpe))
+ def apply(thistpe: Type, supertpe: Type)(implicit ctx: Context): Type =
+ if (ctx.erasedTypes) thistpe
+ else unique(new CachedSuperType(thistpe, supertpe))
}
/** A constant type with single `value`. */
@@ -1684,10 +1685,13 @@ object Types {
if (names.isEmpty) parent
else make(RefinedType(parent, names.head, infoFns.head), names.tail, infoFns.tail)
- def apply(parent: Type, name: Name, infoFn: RefinedType => Type)(implicit ctx: Context): RefinedType =
+ def apply(parent: Type, name: Name, infoFn: RefinedType => Type)(implicit ctx: Context): RefinedType = {
+ assert(!ctx.erasedTypes)
ctx.base.uniqueRefinedTypes.enterIfNew(new CachedRefinedType(parent, name, infoFn)).checkInst
+ }
def apply(parent: Type, name: Name, info: Type)(implicit ctx: Context): RefinedType = {
+ assert(!ctx.erasedTypes)
ctx.base.uniqueRefinedTypes.enterIfNew(parent, name, info).checkInst
}
}
diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala
index 86151fae2..ba6e1dbe0 100644
--- a/src/dotty/tools/dotc/transform/Erasure.scala
+++ b/src/dotty/tools/dotc/transform/Erasure.scala
@@ -309,9 +309,6 @@ object Erasure {
}
}
- override def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): TypeTree =
- promote(tree)
-
override def ensureNoLocalRefs(block: Block, pt: Type, forcedDefined: Boolean = false)(implicit ctx: Context): Tree =
block // optimization, no checking needed, as block symbols do not change.
diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala
index 2edaabdf2..bd7e351e1 100644
--- a/src/dotty/tools/dotc/transform/TreeChecker.scala
+++ b/src/dotty/tools/dotc/transform/TreeChecker.scala
@@ -12,6 +12,7 @@ import core.Flags._
import core.Constants._
import core.StdNames._
import core.Decorators._
+import core.TypeErasure.isErasedType
import typer._
import typer.ErrorReporting._
import reporting.ThrowingReporter
@@ -42,7 +43,7 @@ class TreeChecker {
object Checker extends ReTyper {
override def typed(tree: untpd.Tree, pt: Type)(implicit ctx: Context) = try {
- tree match {
+ val res = tree match {
case _: untpd.UnApply =>
// can't recheck patterns
tree.asInstanceOf[tpd.Tree]
@@ -66,6 +67,8 @@ class TreeChecker {
assert(isSubType(tree1.tpe, tree.typeOpt), divergenceMsg(tree1.tpe, tree.typeOpt))
tree1
}
+ if (ctx.erasedTypes) assertErased(res)
+ res
} catch {
case ex: Throwable =>
println(i"exception while checking $tree of class ${tree.getClass} # ${tree.uniqueId}")
@@ -119,6 +122,15 @@ class TreeChecker {
tree
}
}
+
+ def assertErased(tp: Type, tree: Tree = EmptyTree)(implicit ctx: Context): Unit =
+ assert(isErasedType(tp), i"The type $tp - ${tp.toString} of class ${tp.getClass} of tree $tree / ${tree.getClass} is illegal after erasure, phase = ${ctx.phase}")
+
+ def assertErased(tree: Tree)(implicit ctx: Context): Unit = {
+ assertErased(tree.typeOpt, tree)
+ if (!(tree.symbol == defn.Any_isInstanceOf || tree.symbol == defn.Any_asInstanceOf))
+ assertErased(tree.typeOpt.widen, tree)
+ }
}
object TreeChecker extends TreeChecker \ No newline at end of file
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 89cf0b055..f21528da0 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -834,7 +834,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
if (tree.isType) typedType(tree)(superCtx)
else {
val result = typedExpr(tree)(superCtx)
- if ((cls is Trait) && result.tpe.classSymbol.isRealClass)
+ if ((cls is Trait) && result.tpe.classSymbol.isRealClass && !ctx.isAfterTyper)
ctx.error(s"trait may not call constructor of ${result.tpe.classSymbol}", tree.pos)
result
}