summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2012-07-08 11:30:46 +0200
committerAdriaan Moors <adriaan.moors@epfl.ch>2012-07-11 17:40:34 +0200
commit39fc4aa845dab660d9d360f9b6e9fd82f5d765fe (patch)
tree792a4c8b8bfc0948493171a43ff6075c56bdbdc1 /src/reflect
parent2d35dfcffdf227466b22e3920943a3acc6240e7f (diff)
downloadscala-39fc4aa845dab660d9d360f9b6e9fd82f5d765fe.tar.gz
scala-39fc4aa845dab660d9d360f9b6e9fd82f5d765fe.tar.bz2
scala-39fc4aa845dab660d9d360f9b6e9fd82f5d765fe.zip
polymorphic value classes
dropping boxing code, which turned out to be a dead end.
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala10
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala19
-rw-r--r--src/reflect/scala/reflect/internal/transform/Erasure.scala51
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