diff options
Diffstat (limited to 'src/reflect')
-rw-r--r-- | src/reflect/scala/reflect/internal/Symbols.scala | 10 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Types.scala | 19 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/transform/Erasure.scala | 51 |
3 files changed, 62 insertions, 18 deletions
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 77c27126c5..94be7848bf 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -2239,10 +2239,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => base.info.decl(sname) filter (_.hasAccessorFlag) } - /** Return the accessor method of the first parameter of this class. + /** If this is a derived value class, return its unbox method * or NoSymbol if it does not exist. */ - def firstParamAccessor: Symbol = NoSymbol + def derivedValueClassUnbox: Symbol = NoSymbol /** The case module corresponding to this case class * @pre case class is a member of some other class or package @@ -3146,8 +3146,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => clone } - override def firstParamAccessor = - info.decls.find(_ hasAllFlags PARAMACCESSOR | METHOD) getOrElse NoSymbol + override def derivedValueClassUnbox = + (info.decl(nme.unbox)) orElse + (info.decls.find(_ hasAllFlags PARAMACCESSOR | METHOD) getOrElse + NoSymbol) private[this] var childSet: Set[Symbol] = Set() override def children = childSet diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 56cc265e48..0b3e125053 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -66,7 +66,7 @@ import util.Statistics // inst is the instantiation and constr is a list of bounds. case DeBruijnIndex(level, index) // for dependent method types: a type referring to a method parameter. - case ErasedValueType(tp) + case ErasedValueType(clazz, underlying) // only used during erasure of derived value classes. */ @@ -3305,16 +3305,21 @@ trait Types extends api.Types { self: SymbolTable => } } - abstract case class ErasedValueType(sym: Symbol) extends Type { - override def safeToString = sym.name+"$unboxed" + /** A temporary type representing the reasure of a user-defined value type. + * Created during phase reasure, elimintaed again in posterasure. + * @param sym The value class symbol + * @param underlying The underlying type before erasure + */ + abstract case class ErasedValueType(original: TypeRef) extends Type { + override def safeToString = "ErasedValueType("+original+")" } - final class UniqueErasedValueType(sym: Symbol) extends ErasedValueType(sym) with UniqueType + final class UniqueErasedValueType(original: TypeRef) extends ErasedValueType(original) with UniqueType object ErasedValueType { - def apply(sym: Symbol): Type = { - assert(sym ne NoSymbol, "ErasedValueType cannot be NoSymbol") - unique(new UniqueErasedValueType(sym)) + def apply(original: TypeRef): Type = { + assert(original.sym ne NoSymbol, "ErasedValueType over NoSymbol") + unique(new UniqueErasedValueType(original)) } } diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala index 5beec70d62..368d55a59c 100644 --- a/src/reflect/scala/reflect/internal/transform/Erasure.scala +++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala @@ -2,7 +2,7 @@ package scala.reflect package internal package transform -import Flags.PARAMACCESSOR +import Flags.{PARAMACCESSOR, METHOD} trait Erasure { @@ -72,8 +72,37 @@ trait Erasure { if (cls.owner.isClass) cls.owner.tpe else pre // why not cls.isNestedClass? } + def unboxDerivedValueClassMethod(clazz: Symbol): Symbol = + (clazz.info.decl(nme.unbox)) orElse + (clazz.info.decls.find(_ hasAllFlags PARAMACCESSOR | METHOD) getOrElse + NoSymbol) + def underlyingOfValueClass(clazz: Symbol): Type = - clazz.firstParamAccessor.tpe.resultType + clazz.derivedValueClassUnbox.tpe.resultType + + /** The type of the argument of a value class reference after erasure + * This method needs to be called at a phase no later than erasurephase + */ + def erasedValueClassArg(tref: TypeRef): Type = { + assert(!phase.erasedTypes) + val clazz = tref.sym + if (valueClassIsParametric(clazz)) { + val underlying = tref.memberType(clazz.derivedValueClassUnbox).resultType + boxingErasure(underlying) + } else { + scalaErasure(underlyingOfValueClass(clazz)) + } + } + + /** Does this vakue class have an underlying type that's a type parameter of + * the class itself? + * This method needs to be called at a phase no later than erasurephase + */ + def valueClassIsParametric(clazz: Symbol): Boolean = { + assert(!phase.erasedTypes) + clazz.typeParams contains + clazz.derivedValueClassUnbox.tpe.resultType.normalize.typeSymbol + } abstract class ErasureMap extends TypeMap { private lazy val ObjectArray = arrayType(ObjectClass.tpe) @@ -84,15 +113,14 @@ trait Erasure { def eraseNormalClassRef(pre: Type, clazz: Symbol): Type = typeRef(apply(rebindInnerClass(pre, clazz)), clazz, List()) // #2585 - protected def eraseDerivedValueClassRef(clazz: Symbol): Type = - scalaErasure(underlyingOfValueClass(clazz)) + protected def eraseDerivedValueClassRef(tref: TypeRef): Type = erasedValueClassArg(tref) def apply(tp: Type): Type = tp match { case ConstantType(_) => tp case st: SubType => apply(st.supertype) - case TypeRef(pre, sym, args) => + case tref @ TypeRef(pre, sym, args) => if (sym == ArrayClass) if (unboundedGenericArrayLevel(tp) == 1) ObjectClass.tpe else if (args.head.typeSymbol.isBottomClass) ObjectArray @@ -100,7 +128,7 @@ trait Erasure { else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass || sym == NotNullClass) ErasedObject else if (sym == UnitClass) erasedTypeRef(BoxedUnitClass) else if (sym.isRefinementClass) apply(mergeParents(tp.parents)) - else if (sym.isDerivedValueClass) eraseDerivedValueClassRef(sym) + else if (sym.isDerivedValueClass) eraseDerivedValueClassRef(tref) else if (sym.isClass) eraseNormalClassRef(pre, sym) else apply(sym.info) // alias type or abstract type case PolyType(tparams, restpe) => @@ -236,7 +264,8 @@ trait Erasure { * are then later converted to the underlying parameter type in phase posterasure. */ object specialScalaErasure extends ScalaErasureMap { - override def eraseDerivedValueClassRef(clazz: Symbol): Type = ErasedValueType(clazz) + override def eraseDerivedValueClassRef(tref: TypeRef): Type = + ErasedValueType(tref) } object javaErasure extends JavaErasureMap @@ -251,6 +280,14 @@ trait Erasure { } } + object boxingErasure extends ScalaErasureMap { + override def eraseNormalClassRef(pre: Type, clazz: Symbol) = + if (isPrimitiveValueClass(clazz)) boxedClass(clazz).tpe + else super.eraseNormalClassRef(pre, clazz) + override def eraseDerivedValueClassRef(tref: TypeRef) = + super.eraseNormalClassRef(tref.pre, tref.sym) + } + /** The intersection dominator (SLS 3.7) of a list of types is computed as follows. * * - If the list contains one or more occurrences of scala.Array with |