diff options
author | Martin Odersky <odersky@gmail.com> | 2012-02-13 17:18:49 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2012-02-14 18:34:42 +0100 |
commit | 5bbc2d089f0f440612d6219479ea8e5cea0f01a4 (patch) | |
tree | ee5ff64cc9305f57441106c24a9f2828d1690b2c /src/compiler | |
parent | ee560229d1be78294b17ba4b0b6f36e8dd68d376 (diff) | |
download | scala-5bbc2d089f0f440612d6219479ea8e5cea0f01a4.tar.gz scala-5bbc2d089f0f440612d6219479ea8e5cea0f01a4.tar.bz2 scala-5bbc2d089f0f440612d6219479ea8e5cea0f01a4.zip |
Refactoring to control the effects of inline erasure, restricting them to just the erasure phase and its actions.
Diffstat (limited to 'src/compiler')
3 files changed, 51 insertions, 37 deletions
diff --git a/src/compiler/scala/reflect/internal/transform/Erasure.scala b/src/compiler/scala/reflect/internal/transform/Erasure.scala index f8dfd66fbe..2be7ec3190 100644 --- a/src/compiler/scala/reflect/internal/transform/Erasure.scala +++ b/src/compiler/scala/reflect/internal/transform/Erasure.scala @@ -65,17 +65,14 @@ trait Erasure { if (cls.owner.isClass) cls.owner.tpe else pre // why not cls.isNestedClass? } - def valueClassErasure(clazz: Symbol): Type = - clazz.primaryConstructor.info.params.head.tpe - - protected def eraseInlineClassRef(clazz: Symbol): Type = - scalaErasure(valueClassErasure(clazz)) + def underlyingOfValueClass(clazz: Symbol): Type = + clazz.firstParamAccessor.tpe.resultType abstract class ErasureMap extends TypeMap { def mergeParents(parents: List[Type]): Type - def eraseNormalClassRef(pre: Type, clazz: Symbol): Type = - typeRef(apply(rebindInnerClass(pre, clazz)), clazz, List()) // #2585 + protected def eraseInlineClassRef(clazz: Symbol): Type = + scalaErasure(underlyingOfValueClass(clazz)) def apply(tp: Type): Type = { tp match { @@ -92,7 +89,7 @@ trait Erasure { else if (sym == UnitClass) erasedTypeRef(BoxedUnitClass) else if (sym.isRefinementClass) apply(mergeParents(tp.parents)) else if (sym.isInlineClass) eraseInlineClassRef(sym) - else if (sym.isClass) eraseNormalClassRef(pre, sym) + else if (sym.isClass) typeRef(apply(rebindInnerClass(pre, sym)), sym, List()) // #2585 else apply(sym.info) // alias type or abstract type case PolyType(tparams, restpe) => apply(restpe) @@ -159,13 +156,23 @@ trait Erasure { log("Identified divergence between java/scala erasure:\n scala: " + old + "\n java: " + res) } res - } else if (sym.isTerm && sym.owner.isInlineClass) - scalaErasureAvoiding(sym.owner, tp) - else if (sym.isValue && sym.owner.isMethodWithExtension) - scalaErasureAvoiding(sym.owner.owner, tp) - else + } else scalaErasure(tp) } + + /** This is used as the Scala erasure during the erasure phase itself + * It differs from normal erasure in that value classes are erased to ErasedInlineTypes which + * are then later converted to the underlying parameter type in phase posterasure. + */ + def specialErasure(sym: Symbol, tp: Type): Type = + if (sym != NoSymbol && sym.enclClass.isJavaDefined) + erasure(sym, tp) + else if (sym.isTerm && sym.owner.isInlineClass) + specialErasureAvoiding(sym.owner, tp) + else if (sym.isValue && sym.owner.isMethodWithExtension) + specialErasureAvoiding(sym.owner.owner, tp) + else + specialErasure(tp) /** Scala's more precise erasure than java's is problematic as follows: * @@ -179,29 +186,39 @@ trait Erasure { * For this reason and others (such as distinguishing constructors from other methods) * erasure is now (Symbol, Type) => Type rather than Type => Type. */ - object scalaErasure extends ErasureMap { + class ScalaErasureMap extends ErasureMap { /** In scala, calculate a useful parent. * An intersection such as `Object with Trait` erases to Trait. */ def mergeParents(parents: List[Type]): Type = intersectionDominator(parents) } - - def scalaErasureAvoiding(clazz: Symbol, tpe: Type): Type = { + + object scalaErasure extends ScalaErasureMap + + /** This is used as the Scala erasure during the erasure phase itself + * It differs from normal erasure in that value classes are erased to ErasedInlineTypes which + * are then later converted to the underlying parameter type in phase posterasure. + */ + object specialErasure extends ScalaErasureMap { + override def eraseInlineClassRef(clazz: Symbol): Type = ErasedInlineType(clazz) + } + + def specialErasureAvoiding(clazz: Symbol, tpe: Type): Type = { tpe match { case PolyType(tparams, restpe) => - scalaErasureAvoiding(clazz, restpe) + specialErasureAvoiding(clazz, restpe) case ExistentialType(tparams, restpe) => - scalaErasureAvoiding(clazz, restpe) + specialErasureAvoiding(clazz, restpe) case mt @ MethodType(params, restpe) => MethodType( - cloneSymbolsAndModify(params, scalaErasureAvoiding(clazz, _)), + cloneSymbolsAndModify(params, specialErasureAvoiding(clazz, _)), if (restpe.typeSymbol == UnitClass) erasedTypeRef(UnitClass) - else scalaErasureAvoiding(clazz, (mt.resultType(params map (_.tpe))))) + else specialErasureAvoiding(clazz, (mt.resultType(params map (_.tpe))))) case TypeRef(pre, `clazz`, args) => - scalaErasure.eraseNormalClassRef(pre, clazz) + typeRef(pre, clazz, List()) case _ => - scalaErasure(tpe) + specialErasure(tpe) } } @@ -265,25 +282,25 @@ trait Erasure { if (sym == Object_asInstanceOf) sym.info else if (sym == Object_isInstanceOf || sym == ArrayClass) - PolyType(sym.info.typeParams, erasure(sym, sym.info.resultType)) + PolyType(sym.info.typeParams, specialErasure(sym, sym.info.resultType)) else if (sym.isAbstractType) TypeBounds(WildcardType, WildcardType) else if (sym.isTerm && sym.owner == ArrayClass) { if (sym.isClassConstructor) tp match { case MethodType(params, TypeRef(pre, sym1, args)) => - MethodType(cloneSymbolsAndModify(params, erasure(sym, _)), - typeRef(erasure(sym, pre), sym1, args)) + MethodType(cloneSymbolsAndModify(params, specialErasure(sym, _)), + typeRef(specialErasure(sym, pre), sym1, args)) } else if (sym.name == nme.apply) tp else if (sym.name == nme.update) (tp: @unchecked) match { case MethodType(List(index, tvar), restpe) => - MethodType(List(index.cloneSymbol.setInfo(erasure(sym, index.tpe)), tvar), + MethodType(List(index.cloneSymbol.setInfo(specialErasure(sym, index.tpe)), tvar), erasedTypeRef(UnitClass)) } - else erasure(sym, tp) + else specialErasure(sym, tp) } else if ( sym.owner != NoSymbol && sym.owner.owner == ArrayClass && @@ -293,7 +310,7 @@ trait Erasure { // symbol here tp } else { - erasure(sym, tp) + specialErasure(sym, tp) } } } diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 7eb819f058..30448b6eaa 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -335,9 +335,6 @@ abstract class Erasure extends AddInterfaces class UnknownSig extends Exception - override def eraseInlineClassRef(clazz: Symbol): Type = ErasedInlineType(clazz) - - /** The symbol's erased info. This is the type's erasure, except for the following symbols: * * - For $asInstanceOf : [T]T @@ -439,7 +436,7 @@ abstract class Erasure extends AddInterfaces case Unboxed(arg) if arg.tpe.typeSymbol == clazz => log("shortcircuiting unbox -> box "+arg); arg case _ => - New(clazz, cast(tree, valueClassErasure(clazz))) + New(clazz, cast(tree, underlyingOfValueClass(clazz))) } case _ => tree.tpe.typeSymbol match { @@ -913,7 +910,7 @@ abstract class Erasure extends AddInterfaces gen.mkMethodCall( qual1(), fun.symbol, - List(erasure(fun.symbol, arg.tpe)), + List(specialErasure(fun.symbol, arg.tpe)), Nil ), isArrayTest(qual1()) @@ -1067,7 +1064,7 @@ abstract class Erasure extends AddInterfaces && ct.typeValue.typeSymbol != definitions.UnitClass => val erased = ct.typeValue match { case TypeRef(pre, clazz, args) if clazz.isInlineClass => typeRef(pre, clazz, List()) - case tpe => erasure(NoSymbol, tpe) + case tpe => specialErasure(NoSymbol, tpe) } treeCopy.Literal(tree, Constant(erased)) @@ -1087,10 +1084,10 @@ abstract class Erasure extends AddInterfaces val tree1 = preErase(tree) tree1 match { case EmptyTree | TypeTree() => - tree1 setType erasure(NoSymbol, tree1.tpe) + tree1 setType specialErasure(NoSymbol, tree1.tpe) case DefDef(_, _, _, _, tpt, _) => val result = super.transform(tree1) setType null - tpt.tpe = erasure(tree1.symbol, tree1.symbol.tpe).resultType + tpt.tpe = specialErasure(tree1.symbol, tree1.symbol.tpe).resultType result case _ => super.transform(tree1) setType null diff --git a/src/compiler/scala/tools/nsc/transform/PostErasure.scala b/src/compiler/scala/tools/nsc/transform/PostErasure.scala index 1efa9ef3d5..af8de11504 100644 --- a/src/compiler/scala/tools/nsc/transform/PostErasure.scala +++ b/src/compiler/scala/tools/nsc/transform/PostErasure.scala @@ -14,7 +14,7 @@ trait PostErasure extends InfoTransform with TypingTransformers { object elimErasedInline extends TypeMap { def apply(tp: Type) = tp match { - case ErasedInlineType(clazz) => erasure.valueClassErasure(clazz) + case ErasedInlineType(clazz) => erasure.underlyingOfValueClass(clazz) case _ => mapOver(tp) } } |