diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-04-02 11:31:35 +0200 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2013-04-02 15:20:53 +0200 |
commit | 51d96a32f1726f5152b1b6ff9a469944c8a77e94 (patch) | |
tree | ecb17550e07c09acd5db362a3f7ee8b9d4eaacc4 /src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala | |
parent | 00e6c8b9e395cae3b761b848482bc91c7634ec13 (diff) | |
parent | a4785baf83f8655399bcfe865962fe4d1ef48e59 (diff) | |
download | scala-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.scala | 64 |
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) } } |