Permalink
Browse files

Fix for unnecessary InnerClasses for top-level objects.

Mirror classes (with static forwarders) for top-level
objects would get unnecessary InnerClasses entries
in some cases. See the following comment I introduced
to the place I fixed:

We need to make sure that we do not confuse inner classes
of the class  we mirror with inner classes of the class
we are mirroring. These two sets can be different as
seen in this case:

```scala
 class A {
  class B
  def b: B = new B
 }
 object C extends A
```

Here mirror class of C has a static forwarder for
(inherited) method `b` therefore it refers to class `B`
and needs InnerClasses entry. However, the real class
for `C` (named `C$`) is empty and does not refer to `B`
thus does not need InnerClasses entry it.

NOTE: This logic has been refactored in GenASM and
everything is implemented in a much cleaner way by
having two separate buffers.
  • Loading branch information...
gkossakowski committed May 11, 2012
1 parent 2422b06 commit 389a15bf1e63934644e4aa423cac31435438ff36
Showing with 22 additions and 0 deletions.
  1. +22 −0 src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -1159,6 +1159,27 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
*/
def generateMirrorClass(clasz: Symbol, sourceFile: SourceFile) {
import JAccessFlags._
+ /* We need to save inner classes buffer and create a new one to make sure
+ * that we do confuse inner classes of the class we mirror with inner
+ * classes of the class we are mirroring. These two sets can be different
+ * as seen in this case:
+ *
+ * class A {
+ * class B
+ * def b: B = new B
+ * }
+ * object C extends A
+ *
+ * Here mirror class of C has a static forwarder for (inherited) method `b`
+ * therefore it refers to class `B` and needs InnerClasses entry. However,
+ * the real class for `C` (named `C$`) is empty and does not refer to `B`
+ * thus does not need InnerClasses entry it.
+ *
+ * NOTE: This logic has been refactored in GenASM and everything is
+ * implemented in a much cleaner way by having two separate buffers.
+ */
+ val savedInnerClasses = innerClassBuffer
+ innerClassBuffer = mutable.LinkedHashSet[Symbol]()
val moduleName = javaName(clasz) // + "$"
val mirrorName = moduleName.substring(0, moduleName.length() - 1)
val mirrorClass = fjbgContext.JClass(ACC_SUPER | ACC_PUBLIC | ACC_FINAL,
@@ -1172,6 +1193,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
val ssa = scalaSignatureAddingMarker(mirrorClass, clasz.companionSymbol)
addAnnotations(mirrorClass, clasz.annotations ++ ssa)
emitClass(mirrorClass, clasz)
+ innerClassBuffer = savedInnerClasses
}
var linearization: List[BasicBlock] = Nil

0 comments on commit 389a15b

Please sign in to comment.