From 0bcc871e3f4c4331fb53ec0e7087669589a607d6 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 21 Jan 2015 19:57:45 +0100 Subject: 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. --- test/files/jvm/innerClassAttribute/Classes_1.scala | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'test/files/jvm/innerClassAttribute/Classes_1.scala') diff --git a/test/files/jvm/innerClassAttribute/Classes_1.scala b/test/files/jvm/innerClassAttribute/Classes_1.scala index 9c3ea7f013..a2ade70c18 100644 --- a/test/files/jvm/innerClassAttribute/Classes_1.scala +++ b/test/files/jvm/innerClassAttribute/Classes_1.scala @@ -185,3 +185,41 @@ trait A24 extends A24Base { override object Conc extends A24Sym } } + +class SI_9105 { + // the EnclosingMethod attributes depend on the delambdafy strategy (inline vs method) + + // outerClass-inline enclMeth-inline outerClass-method enclMeth-method + val fun = () => { + class A // closure null (*) SI_9105 null + def m: Object = { class B; new B } // closure m$1 SI_9105 m$1 + val f: Object = { class C; new C } // closure null (*) SI_9105 null + } + def met = () => { + class D // closure null (*) SI_9105 met + def m: Object = { class E; new E } // closure m$1 SI_9105 m$1 + val f: Object = { class F; new F } // closure null (*) SI_9105 met + } + + // (*) the originalOwner chain of A (similar for D) is: SI_9105.fun.$anonfun-value.A + // we can get to the anonfun-class (created by uncurry), but not to the apply method. + // + // for C and F, the originalOwner chain is fun.$anonfun-value.f.C. at later phases, the rawowner of f is + // an apply$sp method of the closure class. we could use that as enclosing method, but it would be unsystematic + // (A / D don't have an encl meth either), and also strange to use the $sp, which is a compilation artifact. + // So using `null` looks more like the situation in the source code: C / F are nested classes of the anon-fun, and + // there's no method in between. + + def byName[T](op: => T) = 0 + + val bnV = byName { + class G // closure null (*) SI_9105 null + def m: Object = { class H; new H } // closure m$1 SI_9105 m$1 + val f: Object = { class I; new I } // closure null (*) SI_9105 null + } + def bnM = byName { + class J // closure null (*) SI_9105 bnM + def m: Object = { class K; new K } // closure m$1 SI_9105 m$1 + val f: Object = { class L; new L } // closure null (*) SI_9105 bnM + } +} -- cgit v1.2.3