diff options
author | Martin Odersky <odersky@gmail.com> | 2014-10-07 09:07:14 +0200 |
---|---|---|
committer | Dmitry Petrashko <dmitry.petrashko@gmail.com> | 2014-10-12 10:49:35 +0200 |
commit | 5de255637589b800ffc99ddb3453ccd651bfafc9 (patch) | |
tree | 285d28125822132793223feb84a4530d9126abc4 /src/dotty/tools | |
parent | 2ca36a96aee3f2e5cc9073b8970659180f839f95 (diff) | |
download | dotty-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/tools')
-rw-r--r-- | src/dotty/tools/dotc/TypeErasure.scala | 46 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/Erasure.scala | 8 |
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) } |