summaryrefslogtreecommitdiff
path: root/test/files/jvm/innerClassAttribute/Test.scala
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2015-01-21 19:57:45 +0100
committerLukas Rytz <lukas.rytz@gmail.com>2015-02-07 07:45:47 +0100
commit0bcc871e3f4c4331fb53ec0e7087669589a607d6 (patch)
tree86af55ac347552c35a8d5b9bf1a6085e9177b3fb /test/files/jvm/innerClassAttribute/Test.scala
parentd7b11520222c9e995d27de46fecc19c5a1fa5b74 (diff)
downloadscala-0bcc871e3f4c4331fb53ec0e7087669589a607d6.tar.gz
scala-0bcc871e3f4c4331fb53ec0e7087669589a607d6.tar.bz2
scala-0bcc871e3f4c4331fb53ec0e7087669589a607d6.zip
SI-9105 Fix EnclosingMethod for classes defined in lambdas
This change fixes both GenASM and GenBCode, except for the change to renaming in LamdaLift mentioned below. The reason for an inconsistent EnclosingMethod attribute was the symbol owner chain. Initially, closure class symbols don't exist, they are only created in UnCurry (delambdafy:inline). So walking the originalOwner of a definition does not yield closure classes. The commit also fixes uses of isAnonymousClass, isAnonymousFunction and isDelambdafyFunction in two ways: 1. by phase-travelling to an early phase. after flatten, the name includes the name of outer classes, so the properties may become accidentally true (they check for a substring in the name) 2. by ensuring that the (destructive) renames during LambdaLift don't make the above properties accidentally true. This was in fact the cause for SI-8900.
Diffstat (limited to 'test/files/jvm/innerClassAttribute/Test.scala')
-rw-r--r--test/files/jvm/innerClassAttribute/Test.scala78
1 files changed, 74 insertions, 4 deletions
diff --git a/test/files/jvm/innerClassAttribute/Test.scala b/test/files/jvm/innerClassAttribute/Test.scala
index 3820048cb4..30dc412ff7 100644
--- a/test/files/jvm/innerClassAttribute/Test.scala
+++ b/test/files/jvm/innerClassAttribute/Test.scala
@@ -16,6 +16,8 @@ object Test extends BytecodeTest {
loadClassNode(className).innerClasses.asScala.toList.sortBy(_.name)
}
+ def ownInnerClassNode(n: String) = innerClassNodes(n).filter(_.name == n).head
+
final case class EnclosingMethod(name: String, descriptor: String, outerClass: String)
def enclosingMethod(className: String) = {
val n = loadClassNode(className)
@@ -256,10 +258,10 @@ object Test extends BytecodeTest {
printInnerClassNodes("A20")
- val fun1 = lambdaClass("A20$$anonfun$4", "A20$lambda$1")
- val fun2 = lambdaClass("A20$$anonfun$4$$anonfun$apply$1", "A20$lambda$$$nestedInAnonfun$5$1")
- val fun3 = lambdaClass("A20$$anonfun$4$$anonfun$apply$3", "A20$lambda$$$nestedInAnonfun$5$2")
- val fun4 = lambdaClass("A20$$anonfun$4$$anonfun$apply$3$$anonfun$apply$2", "A20$lambda$$$nestedInAnonfun$7$1")
+ val fun1 = lambdaClass("A20$$anonfun$6", "A20$lambda$1")
+ val fun2 = lambdaClass("A20$$anonfun$6$$anonfun$apply$1", "A20$lambda$$$nestedInAnonfun$5$1")
+ val fun3 = lambdaClass("A20$$anonfun$6$$anonfun$apply$3", "A20$lambda$$$nestedInAnonfun$5$2")
+ val fun4 = lambdaClass("A20$$anonfun$6$$anonfun$apply$3$$anonfun$apply$2", "A20$lambda$$$nestedInAnonfun$7$1")
println("fun1: attribute for itself and the two child closures `() => ()` and `() => () => 1`")
printInnerClassNodes(fun1)
@@ -324,6 +326,73 @@ object Test extends BytecodeTest {
assertMember(defsApiImpl, "A24Base", "DefinitionsApi$class", flags = Flags.ACC_PUBLIC | Flags.ACC_ABSTRACT)
}
+ def testSI_9105() {
+ val isDelambdafyMethod = classpath.findClass("SI_9105$lambda$1").isDefined
+ if (isDelambdafyMethod) {
+ assertEnclosingMethod ("SI_9105$A$2" , "SI_9105", null , null)
+ assertEnclosingMethod ("SI_9105$B$5" , "SI_9105", "m$1", "()Ljava/lang/Object;")
+ assertEnclosingMethod ("SI_9105$C$1" , "SI_9105", null , null)
+ assertEnclosingMethod ("SI_9105$D$1" , "SI_9105", "met", "()Lscala/Function0;")
+ assertEnclosingMethod ("SI_9105$E$1" , "SI_9105", "m$3", "()Ljava/lang/Object;")
+ assertEnclosingMethod ("SI_9105$F$1" , "SI_9105", "met", "()Lscala/Function0;")
+ assertNoEnclosingMethod("SI_9105$lambda$$met$1")
+ assertNoEnclosingMethod("SI_9105$lambda$1")
+ assertNoEnclosingMethod("SI_9105")
+
+ assertLocal(innerClassNodes("SI_9105$A$2").head, "SI_9105$A$2", "A$2")
+ assertLocal(innerClassNodes("SI_9105$B$5").head, "SI_9105$B$5", "B$5")
+ assertLocal(innerClassNodes("SI_9105$C$1").head, "SI_9105$C$1", "C$1")
+ assertLocal(innerClassNodes("SI_9105$D$1").head, "SI_9105$D$1", "D$1")
+ assertLocal(innerClassNodes("SI_9105$E$1").head, "SI_9105$E$1", "E$1")
+ assertLocal(innerClassNodes("SI_9105$F$1").head, "SI_9105$F$1", "F$1")
+
+ // by-name
+ assertEnclosingMethod("SI_9105$G$1", "SI_9105", null , null)
+ assertEnclosingMethod("SI_9105$H$1", "SI_9105", "m$2", "()Ljava/lang/Object;")
+ assertEnclosingMethod("SI_9105$I$1", "SI_9105", null , null)
+ assertEnclosingMethod("SI_9105$J$1", "SI_9105", "bnM", "()I")
+ assertEnclosingMethod("SI_9105$K$2", "SI_9105", "m$4", "()Ljava/lang/Object;")
+ assertEnclosingMethod("SI_9105$L$1", "SI_9105", "bnM", "()I")
+
+ assert(innerClassNodes("SI_9105$lambda$$met$1").isEmpty)
+ assert(innerClassNodes("SI_9105$lambda$1").isEmpty)
+ assert(innerClassNodes("SI_9105").length == 12) // the 12 local classes
+ } else {
+ // comment in innerClassAttribute/Classes_1.scala explains the difference between A / C and D / F.
+ assertEnclosingMethod ("SI_9105$$anonfun$4$A$2" , "SI_9105$$anonfun$4" , null , null)
+ assertEnclosingMethod ("SI_9105$$anonfun$4$B$5" , "SI_9105$$anonfun$4" , "m$1" , "()Ljava/lang/Object;")
+ assertEnclosingMethod ("SI_9105$$anonfun$4$C$1" , "SI_9105$$anonfun$4" , null , null)
+ assertEnclosingMethod ("SI_9105$$anonfun$met$1$D$1", "SI_9105$$anonfun$met$1", null , null)
+ assertEnclosingMethod ("SI_9105$$anonfun$met$1$E$1", "SI_9105$$anonfun$met$1", "m$3" , "()Ljava/lang/Object;")
+ assertEnclosingMethod ("SI_9105$$anonfun$met$1$F$1", "SI_9105$$anonfun$met$1", null , null)
+ assertEnclosingMethod ("SI_9105$$anonfun$4" , "SI_9105" , null , null)
+ assertEnclosingMethod ("SI_9105$$anonfun$met$1" , "SI_9105" , "met" , "()Lscala/Function0;")
+ assertNoEnclosingMethod("SI_9105")
+
+ assertLocal(ownInnerClassNode("SI_9105$$anonfun$4$A$2"), "SI_9105$$anonfun$4$A$2" , "A$2")
+ assertLocal(ownInnerClassNode("SI_9105$$anonfun$4$B$5"), "SI_9105$$anonfun$4$B$5" , "B$5")
+ assertLocal(ownInnerClassNode("SI_9105$$anonfun$4$C$1"), "SI_9105$$anonfun$4$C$1" , "C$1")
+ assertLocal(ownInnerClassNode("SI_9105$$anonfun$met$1$D$1"), "SI_9105$$anonfun$met$1$D$1", "D$1")
+ assertLocal(ownInnerClassNode("SI_9105$$anonfun$met$1$E$1"), "SI_9105$$anonfun$met$1$E$1", "E$1")
+ assertLocal(ownInnerClassNode("SI_9105$$anonfun$met$1$F$1"), "SI_9105$$anonfun$met$1$F$1", "F$1")
+
+ // by-name
+ assertEnclosingMethod("SI_9105$$anonfun$5$G$1", "SI_9105$$anonfun$5", null, null)
+ assertEnclosingMethod("SI_9105$$anonfun$5$H$1", "SI_9105$$anonfun$5", "m$2", "()Ljava/lang/Object;")
+ assertEnclosingMethod("SI_9105$$anonfun$5$I$1", "SI_9105$$anonfun$5", null, null)
+ assertEnclosingMethod("SI_9105$$anonfun$bnM$1$J$1", "SI_9105$$anonfun$bnM$1", null, null)
+ assertEnclosingMethod("SI_9105$$anonfun$bnM$1$K$2", "SI_9105$$anonfun$bnM$1", "m$4", "()Ljava/lang/Object;")
+ assertEnclosingMethod("SI_9105$$anonfun$bnM$1$L$1", "SI_9105$$anonfun$bnM$1", null, null)
+
+ assertAnonymous(ownInnerClassNode("SI_9105$$anonfun$4"), "SI_9105$$anonfun$4")
+ assertAnonymous(ownInnerClassNode("SI_9105$$anonfun$met$1"), "SI_9105$$anonfun$met$1")
+
+ assert(innerClassNodes("SI_9105$$anonfun$4").length == 4) // itself and three of the local classes
+ assert(innerClassNodes("SI_9105$$anonfun$met$1").length == 4) // itself and three of the local classes
+ assert(innerClassNodes("SI_9105").length == 4) // the four anon funs
+ }
+ }
+
def show(): Unit = {
testA1()
testA2()
@@ -347,5 +416,6 @@ object Test extends BytecodeTest {
testA22()
testA23()
testA24()
+ testSI_9105()
}
}