aboutsummaryrefslogtreecommitdiff
path: root/src/dotty
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-10-07 09:07:14 +0200
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2014-10-12 10:49:35 +0200
commit5de255637589b800ffc99ddb3453ccd651bfafc9 (patch)
tree285d28125822132793223feb84a4530d9126abc4 /src/dotty
parent2ca36a96aee3f2e5cc9073b8970659180f839f95 (diff)
downloaddotty-5de255637589b800ffc99ddb3453ccd651bfafc9.tar.gz
dotty-5de255637589b800ffc99ddb3453ccd651bfafc9.tar.bz2
dotty-5de255637589b800ffc99ddb3453ccd651bfafc9.zip
Fixes to TermRefs and others in TypeErasure.
1) TermRefs are now erased to their widened underlying type. The only exception are top-level term refs (e.g. the types of Ident or Select nodes), which are treated as before. Those top-level refs are treated by erasedRef instead of erasure. 2) We make sure that erasure methods are not run after phase erasure. Reason: After erasure underlying types change, which affects itself the result of erasure.
Diffstat (limited to 'src/dotty')
-rw-r--r--src/dotty/tools/dotc/TypeErasure.scala46
-rw-r--r--src/dotty/tools/dotc/transform/Erasure.scala8
2 files changed, 38 insertions, 16 deletions
diff --git a/src/dotty/tools/dotc/TypeErasure.scala b/src/dotty/tools/dotc/TypeErasure.scala
index f6c62cf30..cb3f76c10 100644
--- a/src/dotty/tools/dotc/TypeErasure.scala
+++ b/src/dotty/tools/dotc/TypeErasure.scala
@@ -87,15 +87,36 @@ object TypeErasure {
private val javaSigFn = erasureFn(isJava = true, isSemi = false, isConstructor = false, wildcardOK = true)
private val semiErasureFn = erasureFn(isJava = false, isSemi = true, isConstructor = false, wildcardOK = false)
- def erasure(tp: Type)(implicit ctx: Context): Type = scalaErasureFn(tp)
- def semiErasure(tp: Type)(implicit ctx: Context): Type = semiErasureFn(tp)
+ /** The current context with a phase no later than erasure */
+ private def erasureCtx(implicit ctx: Context) =
+ if (ctx.erasedTypes) ctx.withPhase(ctx.erasurePhase) else ctx
+
+ def erasure(tp: Type)(implicit ctx: Context): Type = scalaErasureFn(tp)(erasureCtx)
+ def semiErasure(tp: Type)(implicit ctx: Context): Type = semiErasureFn(tp)(erasureCtx)
def sigName(tp: Type, isJava: Boolean)(implicit ctx: Context): TypeName = {
val normTp =
if (tp.isRepeatedParam) tp.translateParameterized(defn.RepeatedParamClass, defn.SeqClass)
else tp
- (if (isJava) javaSigFn else scalaSigFn).sigName(normTp)
+ (if (isJava) javaSigFn else scalaSigFn).sigName(normTp)(erasureCtx)
+ }
+
+ /** The erasure of a top-level reference. Differs from normal erasure in that
+ * TermRefs are kept instead of being widened away.
+ */
+ def erasedRef(tp: Type)(implicit ctx: Context): Type = tp match {
+ case tp: TermRef =>
+ assert(tp.symbol.exists, tp)
+ TermRef(erasedRef(tp.prefix), tp.symbol.asTerm)
+ case tp =>
+ erasure(tp)
}
+ /** The erasure of a function result type. Differs from normal erasure in that
+ * Unit is kept instead of being mapped to BoxedUnit.
+ */
+ def eraseResult(tp: Type)(implicit ctx: Context): Type =
+ scalaErasureFn.eraseResult(tp)(erasureCtx)
+
/** The symbol's erased info. This is the type's erasure, except for the following symbols:
*
* - For $asInstanceOf : [T]T
@@ -113,8 +134,8 @@ object TypeErasure {
if ((sym eq defn.Any_asInstanceOf) || (sym eq defn.Any_isInstanceOf)) eraseParamBounds(sym.info.asInstanceOf[PolyType])
else if (sym.isAbstractType) TypeAlias(WildcardType)
- else if (sym.isConstructor) outer.addParam(sym.owner.asClass, erase(tp))
- else erase(tp)
+ else if (sym.isConstructor) outer.addParam(sym.owner.asClass, erase(tp)(erasureCtx))
+ else erase(tp)(erasureCtx)
}
def isUnboundedGeneric(tp: Type)(implicit ctx: Context) = !(
@@ -225,7 +246,7 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
* - For NoType or NoPrefix, the type itself.
* - For any other type, exception.
*/
- def apply(tp: Type)(implicit ctx: Context): Type = tp match {
+ private def apply(tp: Type)(implicit ctx: Context): Type = tp match {
case tp: TypeRef =>
val sym = tp.symbol
if (!sym.isClass) this(tp.info)
@@ -236,8 +257,7 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
if (parent isRef defn.ArrayClass) eraseArray(tp)
else this(parent)
case tp: TermRef =>
- assert(tp.symbol.exists, tp)
- TermRef(this(tp.prefix), tp.symbol.asTerm)
+ this(tp.widen)
case ThisType(_) | SuperType(_, _) =>
tp
case ExprType(rt) =>
@@ -270,7 +290,7 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
if ((cls eq defn.ObjectClass) || cls.isPrimitiveValueClass) Nil
else removeLaterObjects(classParents.mapConserve(eraseTypeRef))
val erasedDecls = decls.filteredScope(d => !d.isType || d.isClass)
- tp.derivedClassInfo(NoPrefix, parents, erasedDecls, this(tp.selfType))
+ tp.derivedClassInfo(NoPrefix, parents, erasedDecls, erasedRef(tp.selfType))
// can't replace selftype by NoType because this would lose the sourceModule link
}
case NoType | NoPrefix | ErrorType | JavaArrayType(_) =>
@@ -279,7 +299,7 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
tp
}
- def eraseArray(tp: RefinedType)(implicit ctx: Context) = {
+ private def eraseArray(tp: RefinedType)(implicit ctx: Context) = {
val defn.ArrayType(elemtp) = tp
if (elemtp derivesFrom defn.NullClass) JavaArrayType(defn.ObjectType)
else if (isUnboundedGeneric(elemtp))
@@ -328,7 +348,7 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
/** The name of the type as it is used in `Signature`s.
* Need to ensure correspondence with erasure!
*/
- def sigName(tp: Type)(implicit ctx: Context): TypeName = tp match {
+ private def sigName(tp: Type)(implicit ctx: Context): TypeName = tp match {
case tp: TypeRef =>
val sym = tp.symbol
if (!sym.isClass) sigName(tp.info)
@@ -338,8 +358,8 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
sigName(this(tp))
case JavaArrayType(elem) =>
sigName(elem) ++ "[]"
- case tp: TypeBounds =>
- sigName(tp.hi)
+ case tp: TermRef =>
+ sigName(tp.widen)
case ExprType(rt) =>
sigName(defn.FunctionType(Nil, rt))
case tp: TypeProxy =>
diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala
index 379a59c0b..0e1b389ff 100644
--- a/src/dotty/tools/dotc/transform/Erasure.scala
+++ b/src/dotty/tools/dotc/transform/Erasure.scala
@@ -234,7 +234,10 @@ object Erasure extends TypeTestsCasts{
class Typer extends typer.ReTyper with NoChecking {
import Boxing._
- def erasedType(tree: untpd.Tree)(implicit ctx: Context): Type = erasure(tree.typeOpt)
+ def erasedType(tree: untpd.Tree)(implicit ctx: Context): Type = tree.typeOpt match {
+ case tp: TermRef if tree.isTerm => erasedRef(tp)
+ case tp => erasure(tp)
+ }
override def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = {
assert(tree.hasType)
@@ -366,8 +369,7 @@ object Erasure extends TypeTestsCasts{
tparams = Nil,
vparamss = ddef.vparamss.flatten :: Nil,
tpt = // keep UnitTypes intact in result position
- if (ddef.tpt.typeOpt isRef defn.UnitClass) untpd.TypeTree(defn.UnitType) withPos ddef.tpt.pos
- else ddef.tpt)
+ untpd.TypedSplice(TypeTree(eraseResult(ddef.tpt.typeOpt)).withPos(ddef.tpt.pos)))
super.typedDefDef(ddef1, sym)
}