summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2015-02-02 15:37:24 +0100
committerLukas Rytz <lukas.rytz@gmail.com>2015-02-07 07:45:51 +0100
commitcd8f2f327106c7e2944afa7ac8b7675262626c1e (patch)
treec4d820e34fd0a975655d7b30f0975e30fe990fdd /src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala
parent1437aa88241d5e99900a86b25c6ce385c2708570 (diff)
downloadscala-cd8f2f327106c7e2944afa7ac8b7675262626c1e.tar.gz
scala-cd8f2f327106c7e2944afa7ac8b7675262626c1e.tar.bz2
scala-cd8f2f327106c7e2944afa7ac8b7675262626c1e.zip
Fix InnerClass/EnclosingMethod for trait impl and specialized classes
Trait implementation classes and specialized classes are always considered top-level in terms of the InnerClass / EnclosingMethod attributes. These attributes describe source-level properties, and such classes are a compilation artifact. Note that the same is true for delambdafy:method closure classes (they are always top-level).
Diffstat (limited to 'src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala24
1 files changed, 19 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala
index 09d78fdf41..fb9804be7f 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala
@@ -22,6 +22,14 @@ final class BCodeAsmCommon[G <: Global](val global: G) {
}
/**
+ * True for classes generated by the Scala compiler that are considered top-level in terms of
+ * the InnerClass / EnclosingMethod classfile attributes. See comment in BTypes.
+ */
+ def considerAsTopLevelImplementationArtifact(classSym: Symbol) = {
+ classSym.isImplClass || classSym.isSpecialized
+ }
+
+ /**
* Cache the value of delambdafy == "inline" for each run. We need to query this value many
* times, so caching makes sense.
*/
@@ -148,7 +156,10 @@ final class BCodeAsmCommon[G <: Global](val global: G) {
if (sym.isClass) sym
else enclosingClass(nextEnclosing(sym))
}
- enclosingClass(nextEnclosing(classSym))
+ val r = enclosingClass(nextEnclosing(classSym))
+ // this should be an assertion, but we are more cautious for now as it was introduced before the 2.11.6 minor release
+ if (considerAsTopLevelImplementationArtifact(r)) devWarning(s"enclosing class of $classSym should not be an implementation artifact class: $r")
+ r
}
final case class EnclosingMethodEntry(owner: String, name: String, methodDescriptor: String)
@@ -162,7 +173,8 @@ final class BCodeAsmCommon[G <: Global](val global: G) {
* on the implementation of GenASM / GenBCode, so they need to be passed in.
*/
def enclosingMethodAttribute(classSym: Symbol, classDesc: Symbol => String, methodDesc: Symbol => String): Option[EnclosingMethodEntry] = {
- if (isAnonymousOrLocalClass(classSym)) {
+ // trait impl classes are always top-level, see comment in BTypes
+ if (isAnonymousOrLocalClass(classSym) && !considerAsTopLevelImplementationArtifact(classSym)) {
val methodOpt = enclosingMethodForEnclosingMethodAttribute(classSym)
debuglog(s"enclosing method for $classSym is $methodOpt (in ${methodOpt.map(_.enclClass)})")
Some(EnclosingMethodEntry(
@@ -191,11 +203,13 @@ final class BCodeAsmCommon[G <: Global](val global: G) {
* The member classes of a class symbol. Note that the result of this method depends on the
* current phase, for example, after lambdalift, all local classes become member of the enclosing
* class.
+ *
+ * Impl classes are always considered top-level, see comment in BTypes.
*/
- def memberClassesOf(classSymbol: Symbol): List[Symbol] = classSymbol.info.decls.collect({
- case sym if sym.isClass =>
+ def memberClassesForInnerClassTable(classSymbol: Symbol): List[Symbol] = classSymbol.info.decls.collect({
+ case sym if sym.isClass && !considerAsTopLevelImplementationArtifact(sym) =>
sym
- case sym if sym.isModule =>
+ case sym if sym.isModule && !considerAsTopLevelImplementationArtifact(sym) => // impl classes get the lateMODULE flag in mixin
val r = exitingPickler(sym.moduleClass)
assert(r != NoSymbol, sym.fullLocationString)
r