summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-04-02 11:31:35 +0200
committerJason Zaugg <jzaugg@gmail.com>2013-04-02 15:20:53 +0200
commit51d96a32f1726f5152b1b6ff9a469944c8a77e94 (patch)
treeecb17550e07c09acd5db362a3f7ee8b9d4eaacc4 /src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
parent00e6c8b9e395cae3b761b848482bc91c7634ec13 (diff)
parenta4785baf83f8655399bcfe865962fe4d1ef48e59 (diff)
downloadscala-51d96a32f1726f5152b1b6ff9a469944c8a77e94.tar.gz
scala-51d96a32f1726f5152b1b6ff9a469944c8a77e94.tar.bz2
scala-51d96a32f1726f5152b1b6ff9a469944c8a77e94.zip
Merge remote tracking branch 'origin/2.10.x' into topic/merge-2.10.x-to-v2.11.0-M2-74-g00e6c8b
Conflicts: bincompat-backward.whitelist.conf bincompat-forward.whitelist.conf build.xml src/compiler/scala/reflect/reify/utils/Extractors.scala src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala src/compiler/scala/tools/nsc/typechecker/Typers.scala src/partest/scala/tools/partest/nest/ReflectiveRunner.scala src/reflect/scala/reflect/internal/Types.scala src/reflect/scala/reflect/runtime/JavaUniverse.scala test/files/run/inline-ex-handlers.check test/files/run/t6223.check test/files/run/t6223.scala test/scaladoc/scalacheck/IndexTest.scala
Diffstat (limited to 'src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala')
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala64
1 files changed, 45 insertions, 19 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 124dd6c995..367825c251 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -41,26 +41,24 @@ abstract class ExplicitOuter extends InfoTransform
private def isInner(clazz: Symbol) =
!clazz.isPackageClass && !clazz.outerClass.isStaticOwner
- private def haveSameOuter(parent: Type, clazz: Symbol) = parent match {
- case TypeRef(pre, sym, _) =>
- val owner = clazz.owner
+ private def haveSameOuter(parent: Type, clazz: Symbol) = {
+ val owner = clazz.owner
+ val parentSym = parent.typeSymbol
- //println(s"have same outer $parent $clazz $sym ${sym.owner} $owner $pre")
-
- sym.isClass && owner.isClass &&
- (owner isSubClass sym.owner) &&
- owner.thisType =:= pre
-
- case _ => false
+ parentSym.isClass && owner.isClass &&
+ (owner isSubClass parentSym.owner) &&
+ owner.thisType =:= parent.prefix
}
/** Does given clazz define an outer field? */
def hasOuterField(clazz: Symbol) = {
- val parents = clazz.info.parents
+ val parent = clazz.info.firstParent
- isInner(clazz) && !clazz.isTrait && {
- parents.isEmpty || !haveSameOuter(parents.head, clazz)
- }
+ // space optimization: inherit the $outer pointer from the parent class if
+ // we know that it will point to the correct instance.
+ def canReuseParentOuterField = !parent.typeSymbol.isJavaDefined && haveSameOuter(parent, clazz)
+
+ isInner(clazz) && !clazz.isTrait && !canReuseParentOuterField
}
private def outerField(clazz: Symbol): Symbol = {
@@ -100,6 +98,29 @@ abstract class ExplicitOuter extends InfoTransform
sym setInfo clazz.outerClass.thisType
}
+ /**
+ * Will the outer accessor of the `clazz` subsume the outer accessor of
+ * `mixin`?
+ *
+ * This arises when an inner object mixes in its companion trait.
+ *
+ * {{{
+ * class C {
+ * trait T { C.this } // C$T$$$outer$ : C
+ * object T extends T { C.this } // C$T$$$outer$ : C.this.type
+ * }
+ * }}}
+ *
+ * See SI-7242.
+ }}
+ */
+ private def skipMixinOuterAccessor(clazz: Symbol, mixin: Symbol) = {
+ // Reliant on the current scheme for name expansion, the expanded name
+ // of the outer accessors in a trait and its companion object are the same.
+ // If the assumption is one day falsified, run/t7424.scala will let us know.
+ clazz.fullName == mixin.fullName
+ }
+
/** <p>
* The type transformation method:
* </p>
@@ -162,10 +183,14 @@ abstract class ExplicitOuter extends InfoTransform
for (mc <- clazz.mixinClasses) {
val mixinOuterAcc: Symbol = exitingExplicitOuter(outerAccessor(mc))
if (mixinOuterAcc != NoSymbol) {
- if (decls1 eq decls) decls1 = decls.cloneScope
- val newAcc = mixinOuterAcc.cloneSymbol(clazz, mixinOuterAcc.flags & ~DEFERRED)
- newAcc setInfo (clazz.thisType memberType mixinOuterAcc)
- decls1 enter newAcc
+ if (skipMixinOuterAccessor(clazz, mc))
+ debuglog(s"Reusing outer accessor symbol of $clazz for the mixin outer accessor of $mc")
+ else {
+ if (decls1 eq decls) decls1 = decls.cloneScope
+ val newAcc = mixinOuterAcc.cloneSymbol(clazz, mixinOuterAcc.flags & ~DEFERRED)
+ newAcc setInfo (clazz.thisType memberType mixinOuterAcc)
+ decls1 enter newAcc
+ }
}
}
}
@@ -370,6 +395,7 @@ abstract class ExplicitOuter extends InfoTransform
val outerAcc = outerAccessor(mixinClass) overridingSymbol currentClass
def mixinPrefix = (currentClass.thisType baseType mixinClass).prefix
assert(outerAcc != NoSymbol, "No outer accessor for inner mixin " + mixinClass + " in " + currentClass)
+ assert(outerAcc.alternatives.size == 1, s"Multiple outer accessors match inner mixin $mixinClass in $currentClass : ${outerAcc.alternatives.map(_.defString)}")
// I added the mixinPrefix.typeArgs.nonEmpty condition to address the
// crash in SI-4970. I feel quite sure this can be improved.
val path = (
@@ -404,7 +430,7 @@ abstract class ExplicitOuter extends InfoTransform
}
if (!currentClass.isTrait)
for (mc <- currentClass.mixinClasses)
- if (outerAccessor(mc) != NoSymbol)
+ if (outerAccessor(mc) != NoSymbol && !skipMixinOuterAccessor(currentClass, mc))
newDefs += mixinOuterAccessorDef(mc)
}
}