summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-10-30 08:42:53 +0100
committerJason Zaugg <jzaugg@gmail.com>2013-11-08 11:39:11 +0100
commitdb4ef5b78be2fb7f954d82a972ab70df28acccfa (patch)
treebc5abbabba1d6d7be89ed5ea2e3e05589e80c340 /src
parent12fe8ef2aff8760a9f0277a7baf74a011753f788 (diff)
downloadscala-db4ef5b78be2fb7f954d82a972ab70df28acccfa.tar.gz
scala-db4ef5b78be2fb7f954d82a972ab70df28acccfa.tar.bz2
scala-db4ef5b78be2fb7f954d82a972ab70df28acccfa.zip
Avoid needless TypeRef allocation during erasure.
- ThisType(some.package) need not be erased, we can let that prefix through unchanged and avoid churning through allocations. - Sharpen the condition in `rebindInnerClass`. The answer to the deleted comment in the code, is "anonymous and local classes", which are specifically excluded in the new formulation. - Finally, detect if erasure of the TypeRef is an identity and reuse the original. Waste not, want not. To expand on the first point, here is what used to happen during erasure: scala> val scalaPack = typeOf[Predef.type].prefix scalaPack: $r.intp.global.Type = scala.type scala> typeDeconstruct.show(scalaPack) res19: String = ThisType(package scala) scala> typeDeconstruct.show(erasure.scalaErasure(scalaPack)) res20: String = TypeRef(TypeSymbol(final class scala extends )) Showing one step of the erasure type map: scala> typeDeconstruct.show(scalaPack.asInstanceOf[SubType].underlying.typeOfThis) res21: String = SingleType(pre = ThisType(package <root>), package scala)
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala2
-rw-r--r--src/reflect/scala/reflect/internal/transform/Erasure.scala28
3 files changed, 19 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index a4854dfbeb..57f3da839a 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -1043,7 +1043,7 @@ abstract class Erasure extends AddInterfaces
case Literal(ct) if ct.tag == ClazzTag
&& ct.typeValue.typeSymbol != definitions.UnitClass =>
val erased = ct.typeValue match {
- case TypeRef(pre, clazz, args) if clazz.isDerivedValueClass => scalaErasure.eraseNormalClassRef(pre, clazz)
+ case tr @ TypeRef(pre, clazz, args) if clazz.isDerivedValueClass => scalaErasure.eraseNormalClassRef(tr)
case tpe => specialScalaErasure(tpe)
}
treeCopy.Literal(tree, Constant(erased))
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index ba785c14bd..bd17c18119 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -885,7 +885,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Is this symbol a constant? */
final def isConstant: Boolean = isStable && isConstantType(tpe.resultType)
- /** Is this class nested in another class or module (not a package)? */
+ /** Is this class nested in another class or module (not a package). Includes locally defined classes. */
def isNestedClass = false
/** Is this class locally defined?
diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala
index 3eb3a4cdf4..6a6668ed05 100644
--- a/src/reflect/scala/reflect/internal/transform/Erasure.scala
+++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala
@@ -73,9 +73,8 @@ trait Erasure {
// included (use pre.baseType(cls.owner)).
//
// This requires that cls.isClass.
- protected def rebindInnerClass(pre: Type, cls: Symbol): Type = {
- if (cls.owner.isClass) cls.owner.tpe_* else pre // why not cls.isNestedClass?
- }
+ protected def rebindInnerClass(pre: Type, cls: Symbol): Type =
+ if (!cls.isTopLevel && !cls.isLocal) cls.owner.tpe_* else pre
/** 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
@@ -104,14 +103,21 @@ trait Erasure {
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
+ def eraseNormalClassRef(tref: TypeRef): Type = {
+ val TypeRef(pre, clazz, args) = tref
+ val pre1 = apply(rebindInnerClass(pre, clazz))
+ val args1 = Nil
+ if ((pre eq pre1) && (args eq args1)) tref // OPT
+ else typeRef(pre1, clazz, args1) // #2585
+ }
protected def eraseDerivedValueClassRef(tref: TypeRef): Type = erasedValueClassArg(tref)
def apply(tp: Type): Type = tp match {
case ConstantType(_) =>
tp
+ case st: ThisType if st.sym.isPackageClass =>
+ tp
case st: SubType =>
apply(st.supertype)
case tref @ TypeRef(pre, sym, args) =>
@@ -123,7 +129,7 @@ trait Erasure {
else if (sym == UnitClass) BoxedUnitTpe
else if (sym.isRefinementClass) apply(mergeParents(tp.parents))
else if (sym.isDerivedValueClass) eraseDerivedValueClassRef(tref)
- else if (sym.isClass) eraseNormalClassRef(pre, sym)
+ else if (sym.isClass) eraseNormalClassRef(tref)
else apply(sym.info asSeenFrom (pre, sym.owner)) // alias type or abstract type
case PolyType(tparams, restpe) =>
apply(restpe)
@@ -151,7 +157,7 @@ trait Erasure {
}
def applyInArray(tp: Type): Type = tp match {
- case TypeRef(pre, sym, args) if (sym.isDerivedValueClass) => eraseNormalClassRef(pre, sym)
+ case tref @ TypeRef(_, sym, _) if sym.isDerivedValueClass => eraseNormalClassRef(tref)
case _ => apply(tp)
}
}
@@ -274,11 +280,11 @@ 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 eraseNormalClassRef(tref: TypeRef) =
+ if (isPrimitiveValueClass(tref.sym)) boxedClass(tref.sym).tpe
+ else super.eraseNormalClassRef(tref)
override def eraseDerivedValueClassRef(tref: TypeRef) =
- super.eraseNormalClassRef(tref.pre, tref.sym)
+ super.eraseNormalClassRef(tref)
}
/** The intersection dominator (SLS 3.7) of a list of types is computed as follows.