From 49b62743dc91ab83565c90187ed851921696cd84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pa=C5=82ka?= Date: Wed, 3 Mar 2021 11:58:40 +0100 Subject: [PATCH 1/2] Fix #4192: Properly set InnerClasses end EnclosingMethod in class files --- .../tools/backend/jvm/BCodeAsmCommon.scala | 8 +- .../tools/backend/jvm/BCodeSkelBuilder.scala | 5 + .../test/dotc/run-test-pickling.blacklist | 1 + tests/run/i4192/Checks.scala | 91 +++++ tests/run/i4192/Test.scala | 5 + tests/run/i4192/TestCases.scala | 340 ++++++++++++++++++ 6 files changed, 446 insertions(+), 4 deletions(-) create mode 100644 tests/run/i4192/Checks.scala create mode 100644 tests/run/i4192/Test.scala create mode 100644 tests/run/i4192/TestCases.scala diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeAsmCommon.scala b/compiler/src/dotty/tools/backend/jvm/BCodeAsmCommon.scala index a7c0a71155ab..5fe63a8cfa61 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeAsmCommon.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeAsmCommon.scala @@ -26,8 +26,8 @@ final class BCodeAsmCommon[I <: DottyBackendInterface](val interface: I) { // always top-level. However, SI-8900 shows an example where the weak name-based implementation // of isDelambdafyFunction failed (for a function declared in a package named "lambda"). classSym.isAnonymousClass || { - val originalOwnerLexicallyEnclosingClass = classSym.originalOwner.originalLexicallyEnclosingClass - originalOwnerLexicallyEnclosingClass != NoSymbol && !originalOwnerLexicallyEnclosingClass.isClass + val originalOwner = classSym.originalOwner + originalOwner != NoSymbol && !originalOwner.isClass } } @@ -59,9 +59,9 @@ final class BCodeAsmCommon[I <: DottyBackendInterface](val interface: I) { def enclosingMethod(sym: Symbol): Option[Symbol] = { if (sym.isClass || sym == NoSymbol) None else if (sym.is(Method)) Some(sym) - else enclosingMethod(sym.originalOwner.originalLexicallyEnclosingClass) + else enclosingMethod(sym.originalOwner) } - enclosingMethod(classSym.originalOwner.originalLexicallyEnclosingClass) + enclosingMethod(classSym.originalOwner) } /** diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala b/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala index 253dc495d9c0..43a926001456 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala @@ -221,6 +221,11 @@ trait BCodeSkelBuilder extends BCodeHelpers { addClassFields() innerClassBufferASM ++= classBTypeFromSymbol(claszSymbol).info.memberClasses + + val companion = claszSymbol.companionClass + if companion.isTopLevelModuleClass then + innerClassBufferASM ++= classBTypeFromSymbol(companion).info.memberClasses + gen(cd.rhs) addInnerClassesASM(cnode, innerClassBufferASM.toList) diff --git a/compiler/test/dotc/run-test-pickling.blacklist b/compiler/test/dotc/run-test-pickling.blacklist index d36314e896d8..4a88c9e35d44 100644 --- a/compiler/test/dotc/run-test-pickling.blacklist +++ b/compiler/test/dotc/run-test-pickling.blacklist @@ -1,6 +1,7 @@ derive-generic.scala eff-dependent.scala enum-java +i4192 i5257.scala i7212 i7868.scala diff --git a/tests/run/i4192/Checks.scala b/tests/run/i4192/Checks.scala new file mode 100644 index 000000000000..d07b57a12647 --- /dev/null +++ b/tests/run/i4192/Checks.scala @@ -0,0 +1,91 @@ +package checks + +import reflect.ClassTag + +/* This test checks whether InnerClasses and EnclosingMethod sections in generated class files are correct + * for different possibilities of nesting of classes in other classes, objects and methods (the attributes are accessed via java reflection). + * Names of nested definitions are derived from the name of their enclosing definition by appending a letter following the scheme below: + * A - a class without a companion object + * B - an object without a companion class + * C - a class with its companion object + * D - a method + * Additionally a number may be added to avoid clashes between definitions from classes and their companion objects + * (1 - defined in the companion class; 2 - defined in the companion object), + * e.g. ACD2 - a method inside the companion object of a class inside a top level class + */ +trait Checks: + val expectedTopLevelChecksCount: Int + val expectedMemberChecksCount: Int + val expectedLocalChecksCount: Int + + var topLevelChecksCount = 0 + var memberChecksCount = 0 + var localChecksCount = 0 + + def verifyChecksCounts() = + assert(topLevelChecksCount == expectedTopLevelChecksCount, + s"top level checks: expected $expectedTopLevelChecksCount but was $topLevelChecksCount") + assert(memberChecksCount == expectedMemberChecksCount, + s"member checks: expected $expectedMemberChecksCount but was $memberChecksCount") + assert(localChecksCount == expectedLocalChecksCount, + s"local checks: expected $expectedLocalChecksCount but was $localChecksCount") + + /** Check JVM class properties of a top level class */ + def checkTopLevel[ThisClass](using thisTag: ClassTag[ThisClass]) = + val cls = thisTag.runtimeClass + assert(cls.getEnclosingClass == null, s"Top level class $cls should have no enclosing class") + assert(cls.getDeclaringClass == null, s"Top level class $cls should have no declaring class") + assert(cls.getEnclosingMethod == null, s"Top level class $cls should have no enclosing method") + topLevelChecksCount += 1 + + /** Check JVM class properties of a member class (defined directly inside another class) */ + def checkMember[ThisClass, EnclosingClass](using thisTag: ClassTag[ThisClass], enclosingTag: ClassTag[EnclosingClass]) = + val cls = thisTag.runtimeClass + def className = cls.simpleName + def enclosingClassName = cls.getEnclosingClass.simpleName + def declaringClassName = cls.getDeclaringClass.simpleName + val expectedEnclosingClassName = enclosingTag.runtimeClass.simpleName match + case "B$" => "B" // classes defined directly in top level objects should be moved to their companion/mirror classes + case "C$" => "C" + case name => name + assert(cls.getEnclosingClass != null, + s"Member class $className should have an enclosing class") + assert(enclosingClassName == expectedEnclosingClassName, + s"The enclosing class of class $className should be $expectedEnclosingClassName but was $enclosingClassName") + assert(cls.getDeclaringClass == cls.getEnclosingClass, + s"The declaring class of class $className should be the same as its enclosing class but was $declaringClassName") + assert(cls.getEnclosingMethod == null, + s"Member class $className should have no enclosing method") + memberChecksCount += 1 + + /** Check JVM class properties of a local class (defined directly inside a method) */ + def checkLocal[ThisClass, EnclosingClass](using thisTag: ClassTag[ThisClass], enclosingTag: ClassTag[EnclosingClass]) = + val cls = thisTag.runtimeClass + def className = cls.simpleName + def enclosingClassName = cls.getEnclosingClass.simpleName + def meth = cls.getEnclosingMethod + val expectedEnclosingClassName = enclosingTag.runtimeClass.simpleName + // extracting method name basing on the described naming convention + // $1 gets added during lambdaLift in case of a method defined inside another method + val expectedEnclosingMethodName = + val prefix = className.init + val suffix = if prefix.filter(_.isLetter).endsWith("DD") then "$1" else "" + prefix ++ suffix + assert(cls.getEnclosingClass != null, + s"Local class $className should have an enclosing class") + assert(enclosingClassName == expectedEnclosingClassName, + s"The enclosing class of class $className should be $expectedEnclosingClassName but was $enclosingClassName") + assert(cls.getDeclaringClass == null, + s"Local class $className should have no declaring class") + assert(meth != null, + s"Local class $className should have an enclosing method") + assert(meth.getName == expectedEnclosingMethodName, + s"The enclosing method of class $className should be $expectedEnclosingMethodName but was ${meth.getName}") + localChecksCount += 1 + + extension (cls: Class[?]) + // java 8 implementation of cls.getSimpleName() is buggy - https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8057919 + def simpleName = cls.getName + .stripSuffix("$1").stripSuffix("$2") + .split("\\.").last + .split("\\$").last diff --git a/tests/run/i4192/Test.scala b/tests/run/i4192/Test.scala new file mode 100644 index 000000000000..1e2cb0b83700 --- /dev/null +++ b/tests/run/i4192/Test.scala @@ -0,0 +1,5 @@ +object Test { + def main(args: Array[String]): Unit = { + foo.bar.Checks.run() + } +} diff --git a/tests/run/i4192/TestCases.scala b/tests/run/i4192/TestCases.scala new file mode 100644 index 000000000000..3677c92992ae --- /dev/null +++ b/tests/run/i4192/TestCases.scala @@ -0,0 +1,340 @@ +package foo.bar + +object Checks extends checks.Checks { + val expectedTopLevelChecksCount = 4 + val expectedMemberChecksCount = 4 * 8 + val expectedLocalChecksCount = 4 * 6 + + def run() = + new A + B + new C + C + + verifyChecksCounts() +} + +import Checks._ + +/* The checked cases are: + * 1) a top level class/object + * 2) a class/object in a top level class/object + * 3) a class in another class/object in a top level class/object + * 4) a class in a method in another class/object in top level class/object + * 5) a class/object in a method in a top level class/object + * 6) a class in a method in another method in a top level class/object + * 7) a class in another class in a method in a top level class/object + * Objects with and without a companion class need to be treated as separate cases + * to ensure this works uniformly whether a mirror class is generated or not. + * For completeness classes without a companion object were added as well. + * + * Self-standing references to objects and constructor calls serve the purpose + * of enforcing initialization and running the checks. + */ + +class A { topLevel => + checkTopLevel[this.type] + + class AA { nestedOnce => + checkMember[this.type, topLevel.type] + + class AAA { checkMember[this.type, nestedOnce.type] } + new AAA + + def AAD(): Unit = { + class AADA { checkLocal[this.type, nestedOnce.type] } + new AADA + } + AAD() + } + new AA + + object AB { nestedOnce => + checkMember[this.type, topLevel.type] + + class ABA { checkMember[this.type, nestedOnce.type] } + new ABA + + def ABD(): Unit = { + class ABDA { checkLocal[this.type, nestedOnce.type] } + new ABDA + } + ABD() + } + AB + + class AC { nestedOnce => + checkMember[this.type, topLevel.type] + + class ACA1 { checkMember[this.type, nestedOnce.type] } + new ACA1 + + def ACD(): Unit = { + class ACDA { checkLocal[this.type, nestedOnce.type] } + new ACDA + } + ACD() + } + new AC + + object AC { nestedOnce => + checkMember[this.type, topLevel.type] + + class ACA2 { checkMember[this.type, nestedOnce.type] } + new ACA2 + + def ACD(): Unit = { + class ACDA { checkLocal[this.type, nestedOnce.type] } + new ACDA + } + ACD() + } + AC + + def AD(): Unit = { + class ADA { nestedTwice => + checkLocal[this.type, topLevel.type] + + class ADAA { checkMember[this.type, nestedTwice.type] } + } + new ADA + + def ADD() = { + class ADDA { checkLocal[this.type, topLevel.type] } + new ADDA + } + ADD() + } + AD() +} + + +object B { topLevel => + checkTopLevel[this.type] + + class BA { nestedOnce => + checkMember[this.type, topLevel.type] + + class BAA { checkMember[this.type, nestedOnce.type] } + new BAA + + def BAD(): Unit = { + class BADA { checkLocal[this.type, nestedOnce.type] } + new BADA + } + BAD() + } + new BA + + object BB { nestedOnce => + checkMember[this.type, topLevel.type] + + class BBA { checkMember[this.type, nestedOnce.type] } + new BBA + + def BBD(): Unit = { + class BBDA { checkLocal[this.type, nestedOnce.type] } + new BBDA + } + BBD() + } + BB + + class BC { nestedOnce => + checkMember[this.type, topLevel.type] + + class BCA1 { checkMember[this.type, nestedOnce.type] } + new BCA1 + + def BCD(): Unit = { + class BCDA { checkLocal[this.type, nestedOnce.type] } + new BCDA + } + BCD() + } + new BC + + object BC { nestedOnce => + checkMember[this.type, topLevel.type] + + class BCA2 { checkMember[this.type, nestedOnce.type] } + new BCA2 + + def BCD(): Unit = { + class BCDA { checkLocal[this.type, nestedOnce.type] } + new BCDA + } + BCD() + } + BC + + def BD(): Unit = { + class BDA { nestedTwice => + checkLocal[this.type, topLevel.type] + + class BDAA { checkMember[this.type, nestedTwice.type] } + } + new BDA + + def BDD() = { + class BDDA { checkLocal[this.type, topLevel.type] } + new BDDA + } + BDD() + } + BD() +} + + +class C { topLevel => + checkTopLevel[this.type] + + class CA1 { nestedOnce => + checkMember[this.type, topLevel.type] + + class CA1A { checkMember[this.type, nestedOnce.type] } + new CA1A + + def CA1D(): Unit = { + class CA1DA { checkLocal[this.type, nestedOnce.type] } + new CA1DA + } + CA1D() + } + new CA1 + + object CB1 { nestedOnce => + checkMember[this.type, topLevel.type] + + class CB1A { checkMember[this.type, nestedOnce.type] } + new CB1A + + def CB1D(): Unit = { + class CB1DA { checkLocal[this.type, nestedOnce.type] } + new CB1DA + } + CB1D() + } + CB1 + + class CC1 { nestedOnce => + checkMember[this.type, topLevel.type] + + class CC1A1 { checkMember[this.type, nestedOnce.type] } + new CC1A1 + + def CC1D(): Unit = { + class CC1DA { checkLocal[this.type, nestedOnce.type] } + new CC1DA + } + CC1D() + } + new CC1 + + object CC1 { nestedOnce => + checkMember[this.type, topLevel.type] + + class CC1A2 { checkMember[this.type, nestedOnce.type] } + new CC1A2 + + def CC1D(): Unit = { + class CC1DA { checkLocal[this.type, nestedOnce.type] } + new CC1DA + } + CC1D() + } + CC1 + + def CD1(): Unit = { + class CD1A { nestedTwice => + checkLocal[this.type, topLevel.type] + + class CD1AA { checkMember[this.type, nestedTwice.type] } + } + new CD1A + + def CD1D() = { + class CD1DA { checkLocal[this.type, topLevel.type] } + new CD1DA + } + CD1D() + } + CD1() +} + + +object C { topLevel => + checkTopLevel[this.type] + + class CA2 { nestedOnce => + checkMember[this.type, topLevel.type] + + class CA2A { checkMember[this.type, nestedOnce.type] } + new CA2A + + def CA2D(): Unit = { + class CA2DA { checkLocal[this.type, nestedOnce.type] } + new CA2DA + } + CA2D() + } + new CA2 + + object CB2 { nestedOnce => + checkMember[this.type, topLevel.type] + + class CB2A { checkMember[this.type, nestedOnce.type] } + new CB2A + + def CB2D(): Unit = { + class CB2DA { checkLocal[this.type, nestedOnce.type] } + new CB2DA + } + CB2D() + } + CB2 + + class CC2 { nestedOnce => + checkMember[this.type, topLevel.type] + + class CC2A1 { checkMember[this.type, nestedOnce.type] } + new CC2A1 + + def CC2D(): Unit = { + class CC2DA { checkLocal[this.type, nestedOnce.type] } + new CC2DA + } + CC2D() + } + new CC2 + + object CC2 { nestedOnce => + checkMember[this.type, topLevel.type] + + class CC2A2 { checkMember[this.type, nestedOnce.type] } + new CC2A2 + + def CC2D(): Unit = { + class CC2DA { checkLocal[this.type, nestedOnce.type] } + new CC2DA + } + CC2D() + } + CC2 + + def CD2(): Unit = { + class CD2A { nestedTwice => + checkLocal[this.type, topLevel.type] + + class CD2AA { checkMember[this.type, nestedTwice.type] } + } + new CD2A + + def CD2D() = { + class CD2DA { checkLocal[this.type, topLevel.type] } + new CD2DA + } + CD2D() + } + CD2() +} From 4d03ef988b085b6fc9237358c673f2af4350a515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pa=C5=82ka?= Date: Mon, 8 Mar 2021 11:32:34 +0100 Subject: [PATCH 2/2] Don't disable pickling tests for #4192 --- .../test/dotc/run-test-pickling.blacklist | 1 - tests/run/i4192/Checks.scala | 41 ++-- tests/run/i4192/TestCases.scala | 186 ++++++++++-------- 3 files changed, 120 insertions(+), 108 deletions(-) diff --git a/compiler/test/dotc/run-test-pickling.blacklist b/compiler/test/dotc/run-test-pickling.blacklist index 4a88c9e35d44..d36314e896d8 100644 --- a/compiler/test/dotc/run-test-pickling.blacklist +++ b/compiler/test/dotc/run-test-pickling.blacklist @@ -1,7 +1,6 @@ derive-generic.scala eff-dependent.scala enum-java -i4192 i5257.scala i7212 i7868.scala diff --git a/tests/run/i4192/Checks.scala b/tests/run/i4192/Checks.scala index d07b57a12647..cb910d81d9ec 100644 --- a/tests/run/i4192/Checks.scala +++ b/tests/run/i4192/Checks.scala @@ -2,17 +2,7 @@ package checks import reflect.ClassTag -/* This test checks whether InnerClasses and EnclosingMethod sections in generated class files are correct - * for different possibilities of nesting of classes in other classes, objects and methods (the attributes are accessed via java reflection). - * Names of nested definitions are derived from the name of their enclosing definition by appending a letter following the scheme below: - * A - a class without a companion object - * B - an object without a companion class - * C - a class with its companion object - * D - a method - * Additionally a number may be added to avoid clashes between definitions from classes and their companion objects - * (1 - defined in the companion class; 2 - defined in the companion object), - * e.g. ACD2 - a method inside the companion object of a class inside a top level class - */ + trait Checks: val expectedTopLevelChecksCount: Int val expectedMemberChecksCount: Int @@ -30,22 +20,25 @@ trait Checks: assert(localChecksCount == expectedLocalChecksCount, s"local checks: expected $expectedLocalChecksCount but was $localChecksCount") + // The methods below rely on the naming convention described in TestCases.scala + /** Check JVM class properties of a top level class */ - def checkTopLevel[ThisClass](using thisTag: ClassTag[ThisClass]) = - val cls = thisTag.runtimeClass + def checkTopLevel(self: AnyRef) = + val cls = self.getClass assert(cls.getEnclosingClass == null, s"Top level class $cls should have no enclosing class") assert(cls.getDeclaringClass == null, s"Top level class $cls should have no declaring class") assert(cls.getEnclosingMethod == null, s"Top level class $cls should have no enclosing method") topLevelChecksCount += 1 /** Check JVM class properties of a member class (defined directly inside another class) */ - def checkMember[ThisClass, EnclosingClass](using thisTag: ClassTag[ThisClass], enclosingTag: ClassTag[EnclosingClass]) = - val cls = thisTag.runtimeClass + def checkMember(self: AnyRef, outer: AnyRef) = + val cls = self.getClass def className = cls.simpleName def enclosingClassName = cls.getEnclosingClass.simpleName def declaringClassName = cls.getDeclaringClass.simpleName - val expectedEnclosingClassName = enclosingTag.runtimeClass.simpleName match - case "B$" => "B" // classes defined directly in top level objects should be moved to their companion/mirror classes + // Classes defined directly in top level objects should be moved to their companion/mirror classes + val expectedEnclosingClassName = outer.getClass.simpleName match + case "B$" => "B" case "C$" => "C" case name => name assert(cls.getEnclosingClass != null, @@ -59,12 +52,12 @@ trait Checks: memberChecksCount += 1 /** Check JVM class properties of a local class (defined directly inside a method) */ - def checkLocal[ThisClass, EnclosingClass](using thisTag: ClassTag[ThisClass], enclosingTag: ClassTag[EnclosingClass]) = - val cls = thisTag.runtimeClass + def checkLocal(self: AnyRef, outer: AnyRef) = + val cls = self.getClass def className = cls.simpleName def enclosingClassName = cls.getEnclosingClass.simpleName - def meth = cls.getEnclosingMethod - val expectedEnclosingClassName = enclosingTag.runtimeClass.simpleName + def method = cls.getEnclosingMethod + val expectedEnclosingClassName = outer.getClass.simpleName // extracting method name basing on the described naming convention // $1 gets added during lambdaLift in case of a method defined inside another method val expectedEnclosingMethodName = @@ -77,10 +70,10 @@ trait Checks: s"The enclosing class of class $className should be $expectedEnclosingClassName but was $enclosingClassName") assert(cls.getDeclaringClass == null, s"Local class $className should have no declaring class") - assert(meth != null, + assert(method != null, s"Local class $className should have an enclosing method") - assert(meth.getName == expectedEnclosingMethodName, - s"The enclosing method of class $className should be $expectedEnclosingMethodName but was ${meth.getName}") + assert(method.getName == expectedEnclosingMethodName, + s"The enclosing method of class $className should be $expectedEnclosingMethodName but was ${method.getName}") localChecksCount += 1 extension (cls: Class[?]) diff --git a/tests/run/i4192/TestCases.scala b/tests/run/i4192/TestCases.scala index 3677c92992ae..33b4e458ebe7 100644 --- a/tests/run/i4192/TestCases.scala +++ b/tests/run/i4192/TestCases.scala @@ -1,5 +1,32 @@ package foo.bar +/* This test checks whether InnerClasses and EnclosingMethod sections in generated class files are correct + * for different possibilities of nesting of classes in other classes, objects and methods (the attributes are accessed via java reflection). + * The checked cases are: + * 1) a top level class/object + * 2) a class/object in a top level class/object + * 3) a class in another class/object in a top level class/object + * 4) a class in a method in another class/object in top level class/object + * 5) a class/object in a method in a top level class/object + * 6) a class in a method in another method in a top level class/object + * 7) a class in another class in a method in a top level class/object + * Objects with and without a companion class need to be treated as separate cases + * to ensure this works uniformly whether a mirror class is generated or not. + * For completeness classes without a companion object were added as well. + * + * Names of nested definitions are derived from the name of their enclosing definition by appending a letter following the scheme below: + * A - a class without a companion object + * B - an object without a companion class + * C - a class with its companion object + * D - a method + * Additionally a number may be added to avoid clashes between definitions from classes and their companion objects + * (1 - defined in the companion class; 2 - defined in the companion object), + * e.g. ACD2 - a method inside the companion object of a class inside a top level class + * + * Self-standing references to objects and constructor calls serve the purpose + * of enforcing initialization and running the checks. + */ + object Checks extends checks.Checks { val expectedTopLevelChecksCount = 4 val expectedMemberChecksCount = 4 * 8 @@ -16,47 +43,34 @@ object Checks extends checks.Checks { import Checks._ -/* The checked cases are: - * 1) a top level class/object - * 2) a class/object in a top level class/object - * 3) a class in another class/object in a top level class/object - * 4) a class in a method in another class/object in top level class/object - * 5) a class/object in a method in a top level class/object - * 6) a class in a method in another method in a top level class/object - * 7) a class in another class in a method in a top level class/object - * Objects with and without a companion class need to be treated as separate cases - * to ensure this works uniformly whether a mirror class is generated or not. - * For completeness classes without a companion object were added as well. - * - * Self-standing references to objects and constructor calls serve the purpose - * of enforcing initialization and running the checks. - */ class A { topLevel => - checkTopLevel[this.type] + checkTopLevel(this) class AA { nestedOnce => - checkMember[this.type, topLevel.type] + checkMember(this, topLevel) - class AAA { checkMember[this.type, nestedOnce.type] } + class AAA { checkMember(this, nestedOnce) } new AAA def AAD(): Unit = { - class AADA { checkLocal[this.type, nestedOnce.type] } + class AADA { checkLocal(this, nestedOnce) } new AADA } AAD() } new AA - object AB { nestedOnce => - checkMember[this.type, topLevel.type] + object AB { + val nestedOnce = this // self alias cannot be used uniformly here: https://github.com/lampepfl/dotty/issues/11648 - class ABA { checkMember[this.type, nestedOnce.type] } + checkMember(this, topLevel) + + class ABA { checkMember(this, nestedOnce) } new ABA def ABD(): Unit = { - class ABDA { checkLocal[this.type, nestedOnce.type] } + class ABDA { checkLocal(this, nestedOnce) } new ABDA } ABD() @@ -64,27 +78,29 @@ class A { topLevel => AB class AC { nestedOnce => - checkMember[this.type, topLevel.type] + checkMember(this, topLevel) - class ACA1 { checkMember[this.type, nestedOnce.type] } + class ACA1 { checkMember(this, nestedOnce) } new ACA1 def ACD(): Unit = { - class ACDA { checkLocal[this.type, nestedOnce.type] } + class ACDA { checkLocal(this, nestedOnce) } new ACDA } ACD() } new AC - object AC { nestedOnce => - checkMember[this.type, topLevel.type] + object AC { + val nestedOnce = this + + checkMember(this, topLevel) - class ACA2 { checkMember[this.type, nestedOnce.type] } + class ACA2 { checkMember(this, nestedOnce) } new ACA2 def ACD(): Unit = { - class ACDA { checkLocal[this.type, nestedOnce.type] } + class ACDA { checkLocal(this, nestedOnce) } new ACDA } ACD() @@ -93,14 +109,14 @@ class A { topLevel => def AD(): Unit = { class ADA { nestedTwice => - checkLocal[this.type, topLevel.type] + checkLocal(this, topLevel) - class ADAA { checkMember[this.type, nestedTwice.type] } + class ADAA { checkMember(this, nestedTwice) } } new ADA def ADD() = { - class ADDA { checkLocal[this.type, topLevel.type] } + class ADDA { checkLocal(this, topLevel) } new ADDA } ADD() @@ -110,16 +126,16 @@ class A { topLevel => object B { topLevel => - checkTopLevel[this.type] + checkTopLevel(this) class BA { nestedOnce => - checkMember[this.type, topLevel.type] + checkMember(this, topLevel) - class BAA { checkMember[this.type, nestedOnce.type] } + class BAA { checkMember(this, nestedOnce) } new BAA def BAD(): Unit = { - class BADA { checkLocal[this.type, nestedOnce.type] } + class BADA { checkLocal(this, nestedOnce) } new BADA } BAD() @@ -127,13 +143,13 @@ object B { topLevel => new BA object BB { nestedOnce => - checkMember[this.type, topLevel.type] + checkMember(this, topLevel) - class BBA { checkMember[this.type, nestedOnce.type] } + class BBA { checkMember(this, nestedOnce) } new BBA def BBD(): Unit = { - class BBDA { checkLocal[this.type, nestedOnce.type] } + class BBDA { checkLocal(this, nestedOnce) } new BBDA } BBD() @@ -141,13 +157,13 @@ object B { topLevel => BB class BC { nestedOnce => - checkMember[this.type, topLevel.type] + checkMember(this, topLevel) - class BCA1 { checkMember[this.type, nestedOnce.type] } + class BCA1 { checkMember(this, nestedOnce) } new BCA1 def BCD(): Unit = { - class BCDA { checkLocal[this.type, nestedOnce.type] } + class BCDA { checkLocal(this, nestedOnce) } new BCDA } BCD() @@ -155,13 +171,13 @@ object B { topLevel => new BC object BC { nestedOnce => - checkMember[this.type, topLevel.type] + checkMember(this, topLevel) - class BCA2 { checkMember[this.type, nestedOnce.type] } + class BCA2 { checkMember(this, nestedOnce) } new BCA2 def BCD(): Unit = { - class BCDA { checkLocal[this.type, nestedOnce.type] } + class BCDA { checkLocal(this, nestedOnce) } new BCDA } BCD() @@ -170,14 +186,14 @@ object B { topLevel => def BD(): Unit = { class BDA { nestedTwice => - checkLocal[this.type, topLevel.type] + checkLocal(this, topLevel) - class BDAA { checkMember[this.type, nestedTwice.type] } + class BDAA { checkMember(this, nestedTwice) } } new BDA def BDD() = { - class BDDA { checkLocal[this.type, topLevel.type] } + class BDDA { checkLocal(this, topLevel) } new BDDA } BDD() @@ -187,30 +203,32 @@ object B { topLevel => class C { topLevel => - checkTopLevel[this.type] + checkTopLevel(this) class CA1 { nestedOnce => - checkMember[this.type, topLevel.type] + checkMember(this, topLevel) - class CA1A { checkMember[this.type, nestedOnce.type] } + class CA1A { checkMember(this, nestedOnce) } new CA1A def CA1D(): Unit = { - class CA1DA { checkLocal[this.type, nestedOnce.type] } + class CA1DA { checkLocal(this, nestedOnce) } new CA1DA } CA1D() } new CA1 - object CB1 { nestedOnce => - checkMember[this.type, topLevel.type] + object CB1 { + val nestedOnce = this - class CB1A { checkMember[this.type, nestedOnce.type] } + checkMember(this, topLevel) + + class CB1A { checkMember(this, nestedOnce) } new CB1A def CB1D(): Unit = { - class CB1DA { checkLocal[this.type, nestedOnce.type] } + class CB1DA { checkLocal(this, nestedOnce) } new CB1DA } CB1D() @@ -218,27 +236,29 @@ class C { topLevel => CB1 class CC1 { nestedOnce => - checkMember[this.type, topLevel.type] + checkMember(this, topLevel) - class CC1A1 { checkMember[this.type, nestedOnce.type] } + class CC1A1 { checkMember(this, nestedOnce) } new CC1A1 def CC1D(): Unit = { - class CC1DA { checkLocal[this.type, nestedOnce.type] } + class CC1DA { checkLocal(this, nestedOnce) } new CC1DA } CC1D() } new CC1 - object CC1 { nestedOnce => - checkMember[this.type, topLevel.type] + object CC1 { + val nestedOnce = this + + checkMember(this, topLevel) - class CC1A2 { checkMember[this.type, nestedOnce.type] } + class CC1A2 { checkMember(this, nestedOnce) } new CC1A2 def CC1D(): Unit = { - class CC1DA { checkLocal[this.type, nestedOnce.type] } + class CC1DA { checkLocal(this, nestedOnce) } new CC1DA } CC1D() @@ -247,14 +267,14 @@ class C { topLevel => def CD1(): Unit = { class CD1A { nestedTwice => - checkLocal[this.type, topLevel.type] + checkLocal(this, topLevel) - class CD1AA { checkMember[this.type, nestedTwice.type] } + class CD1AA { checkMember(this, nestedTwice) } } new CD1A def CD1D() = { - class CD1DA { checkLocal[this.type, topLevel.type] } + class CD1DA { checkLocal(this, topLevel) } new CD1DA } CD1D() @@ -264,16 +284,16 @@ class C { topLevel => object C { topLevel => - checkTopLevel[this.type] + checkTopLevel(this) class CA2 { nestedOnce => - checkMember[this.type, topLevel.type] + checkMember(this, topLevel) - class CA2A { checkMember[this.type, nestedOnce.type] } + class CA2A { checkMember(this, nestedOnce) } new CA2A def CA2D(): Unit = { - class CA2DA { checkLocal[this.type, nestedOnce.type] } + class CA2DA { checkLocal(this, nestedOnce) } new CA2DA } CA2D() @@ -281,13 +301,13 @@ object C { topLevel => new CA2 object CB2 { nestedOnce => - checkMember[this.type, topLevel.type] + checkMember(this, topLevel) - class CB2A { checkMember[this.type, nestedOnce.type] } + class CB2A { checkMember(this, nestedOnce) } new CB2A def CB2D(): Unit = { - class CB2DA { checkLocal[this.type, nestedOnce.type] } + class CB2DA { checkLocal(this, nestedOnce) } new CB2DA } CB2D() @@ -295,13 +315,13 @@ object C { topLevel => CB2 class CC2 { nestedOnce => - checkMember[this.type, topLevel.type] + checkMember(this, topLevel) - class CC2A1 { checkMember[this.type, nestedOnce.type] } + class CC2A1 { checkMember(this, nestedOnce) } new CC2A1 def CC2D(): Unit = { - class CC2DA { checkLocal[this.type, nestedOnce.type] } + class CC2DA { checkLocal(this, nestedOnce) } new CC2DA } CC2D() @@ -309,13 +329,13 @@ object C { topLevel => new CC2 object CC2 { nestedOnce => - checkMember[this.type, topLevel.type] + checkMember(this, topLevel) - class CC2A2 { checkMember[this.type, nestedOnce.type] } + class CC2A2 { checkMember(this, nestedOnce) } new CC2A2 def CC2D(): Unit = { - class CC2DA { checkLocal[this.type, nestedOnce.type] } + class CC2DA { checkLocal(this, nestedOnce) } new CC2DA } CC2D() @@ -324,14 +344,14 @@ object C { topLevel => def CD2(): Unit = { class CD2A { nestedTwice => - checkLocal[this.type, topLevel.type] + checkLocal(this, topLevel) - class CD2AA { checkMember[this.type, nestedTwice.type] } + class CD2AA { checkMember(this, nestedTwice) } } new CD2A def CD2D() = { - class CD2DA { checkLocal[this.type, topLevel.type] } + class CD2DA { checkLocal(this, topLevel) } new CD2DA } CD2D()