diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InnerClassesLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InnerClassesLowering.kt index b639c4f3eb9..f7728090912 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InnerClassesLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InnerClassesLowering.kt @@ -77,10 +77,20 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass { irClass.transformChildrenVoid(VariableRemapper(oldConstructorParameterToNew)) irClass.transformChildrenVoid(object : IrElementTransformerVoid() { + private var enclosingConstructor: IrConstructor? = null + // TODO: maybe add another transformer that skips specified elements override fun visitClass(declaration: IrClass): IrStatement = declaration + override fun visitConstructor(declaration: IrConstructor): IrStatement = + try { + enclosingConstructor = declaration + super.visitConstructor(declaration) + } finally { + enclosingConstructor = null + } + override fun visitGetValue(expression: IrGetValue): IrExpression { expression.transformChildrenVoid(this) @@ -100,8 +110,14 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass { return expression } - val outerThisField = context.declarationFactory.getOuterThisField(innerClass) - irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField.symbol, outerThisField.type, irThis, origin) + irThis = if (enclosingConstructor != null && irClass == innerClass) { + // Might be before a super() call (e.g. an argument to one), in which case the JVM bytecode verifier will reject + // an attempt to access the field. Good thing we have a local variable as well. + IrGetValueImpl(startOffset, endOffset, enclosingConstructor!!.valueParameters[0].symbol, origin) + } else { + val outerThisField = context.declarationFactory.getOuterThisField(innerClass) + IrGetFieldImpl(startOffset, endOffset, outerThisField.symbol, outerThisField.type, irThis, origin) + } innerClass = innerClass.parentAsClass } return irThis diff --git a/compiler/testData/codegen/box/classes/inheritedInnerClass.kt b/compiler/testData/codegen/box/classes/inheritedInnerClass.kt index 10e7fd31c5b..82bd91e93cd 100644 --- a/compiler/testData/codegen/box/classes/inheritedInnerClass.kt +++ b/compiler/testData/codegen/box/classes/inheritedInnerClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR class Outer() { open inner class InnerBase() { } diff --git a/compiler/testData/codegen/box/classes/inner/kt6708.kt b/compiler/testData/codegen/box/classes/inner/kt6708.kt index efdadc30838..be556a42996 100644 --- a/compiler/testData/codegen/box/classes/inner/kt6708.kt +++ b/compiler/testData/codegen/box/classes/inner/kt6708.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR open class A() { open inner class InnerA } @@ -10,4 +9,4 @@ class B : A() { fun box(): String { B().InnerB() return "OK" -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/box/classes/propertyInInitializer.kt b/compiler/testData/codegen/box/classes/propertyInInitializer.kt index 5b7f4051f7b..bd8aa833063 100644 --- a/compiler/testData/codegen/box/classes/propertyInInitializer.kt +++ b/compiler/testData/codegen/box/classes/propertyInInitializer.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR class Outer() { val s = "xyzzy" diff --git a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/constructorParameterAndLocalCapturedInLambdaInLocalClass.kt b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/constructorParameterAndLocalCapturedInLambdaInLocalClass.kt index 45546aa0964..56909dc9578 100644 --- a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/constructorParameterAndLocalCapturedInLambdaInLocalClass.kt +++ b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/constructorParameterAndLocalCapturedInLambdaInLocalClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR open class Base(val fn: () -> String) fun box(): String { @@ -9,4 +8,4 @@ fun box(): String { } return Local().Inner("K").fn() -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/constructorParameterCapturedInLambdaInLocalClass2.kt b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/constructorParameterCapturedInLambdaInLocalClass2.kt index e662921e638..ee3f6949825 100644 --- a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/constructorParameterCapturedInLambdaInLocalClass2.kt +++ b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/constructorParameterCapturedInLambdaInLocalClass2.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR open class Base(val fn: () -> String) fun box(): String { @@ -7,4 +6,4 @@ fun box(): String { } return Local("OK").Inner().fn() -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/kt13454.kt b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/kt13454.kt index 83b5c2a98fc..8bb36a828c9 100644 --- a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/kt13454.kt +++ b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/kt13454.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR open class Foo(val x: () -> String) class Outer { @@ -7,4 +6,4 @@ class Outer { inner class Inner : Foo({ s }) } -fun box() = Outer().Inner().x() \ No newline at end of file +fun box() = Outer().Inner().x() diff --git a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/kt14148.kt b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/kt14148.kt index e1853fc4b3f..ca3f5a95df5 100644 --- a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/kt14148.kt +++ b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/kt14148.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR interface Test { fun test(): String } @@ -15,4 +14,4 @@ open class Outer(val x: String) { ) } -fun box() = Outer("OK").JavacBug().test.test() \ No newline at end of file +fun box() = Outer("OK").JavacBug().test.test() diff --git a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/localCapturedInLambdaInInnerClassInLocalClass.kt b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/localCapturedInLambdaInInnerClassInLocalClass.kt index 98d323183e3..38ec2b6e3c9 100644 --- a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/localCapturedInLambdaInInnerClassInLocalClass.kt +++ b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/localCapturedInLambdaInInnerClassInLocalClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR open class Base(val fn: () -> String) fun box(): String { @@ -9,4 +8,4 @@ fun box(): String { } return Local().Inner().fn() -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInFunctionLiteral.kt b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInFunctionLiteral.kt index 4c24e0aae11..21f2ddab94c 100644 --- a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInFunctionLiteral.kt +++ b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInFunctionLiteral.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR open class Base(val callback: () -> String) class Outer { @@ -12,4 +11,4 @@ class Outer { } fun box(): String = - Outer().Inner().callback() \ No newline at end of file + Outer().Inner().callback() diff --git a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInLambda.kt b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInLambda.kt index b21d3d4bd25..4d5b5a259cf 100644 --- a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInLambda.kt +++ b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInLambda.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR open class Base(val callback: () -> String) class Outer { diff --git a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInLambda2.kt b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInLambda2.kt index 5412eea0118..37f31ada1a1 100644 --- a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInLambda2.kt +++ b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInLambda2.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR open class Base(val callback: () -> String) class Outer { @@ -11,4 +10,4 @@ class Outer { } fun box(): String = - Outer().Inner1().Inner2().callback() \ No newline at end of file + Outer().Inner1().Inner2().callback() diff --git a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInLambdaInSecondaryConstructor.kt b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInLambdaInSecondaryConstructor.kt index 0baadfdf169..925f6840dc7 100644 --- a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInLambdaInSecondaryConstructor.kt +++ b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInLambdaInSecondaryConstructor.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR open class Base(val callback: () -> String) class Outer { @@ -10,4 +9,4 @@ class Outer { } fun box(): String = - Outer().Inner().callback() \ No newline at end of file + Outer().Inner().callback() diff --git a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInLambdaInSubExpression.kt b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInLambdaInSubExpression.kt index b1f2305fc4f..b9d634b53e1 100644 --- a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInLambdaInSubExpression.kt +++ b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInLambdaInSubExpression.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR open class Foo(val x: () -> String) open class Foo2(val foo: Foo) diff --git a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInNestedLambda.kt b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInNestedLambda.kt index 8a6b095672c..d64208612bc 100644 --- a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInNestedLambda.kt +++ b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInNestedLambda.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR open class Base(val callback: () -> String) class Outer { @@ -8,4 +7,4 @@ class Outer { } fun box(): String = - Outer().Inner().callback() \ No newline at end of file + Outer().Inner().callback() diff --git a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInNestedObject.kt b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInNestedObject.kt index 544c4c0576d..67c2e5359e4 100644 --- a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInNestedObject.kt +++ b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInNestedObject.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR interface Callback { fun invoke(): String } @@ -19,4 +18,4 @@ class Outer { } fun box(): String = - Outer().Inner().callback.invoke() \ No newline at end of file + Outer().Inner().callback.invoke() diff --git a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInObject.kt b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInObject.kt index caf1e5941cd..af592a9d48a 100644 --- a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInObject.kt +++ b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInObject.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR interface Callback { fun invoke(): String } @@ -16,4 +15,4 @@ class Outer { } fun box(): String = - Outer().Inner().callback.invoke() \ No newline at end of file + Outer().Inner().callback.invoke() diff --git a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInObject2.kt b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInObject2.kt index accdf0622f7..da9afc36cd3 100644 --- a/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInObject2.kt +++ b/compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInObject2.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR interface Callback { fun invoke(): String } @@ -18,4 +17,4 @@ class Outer { } fun box(): String = - Outer().Inner1().Inner2().callback.invoke() \ No newline at end of file + Outer().Inner1().Inner2().callback.invoke() diff --git a/compiler/testData/codegen/box/innerNested/innerJavaClass.kt b/compiler/testData/codegen/box/innerNested/innerJavaClass.kt index f33fdb142db..da291521d05 100644 --- a/compiler/testData/codegen/box/innerNested/innerJavaClass.kt +++ b/compiler/testData/codegen/box/innerNested/innerJavaClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // FILE: JavaClass.java diff --git a/compiler/testData/codegen/box/innerNested/passingOuterRef.kt b/compiler/testData/codegen/box/innerNested/passingOuterRef.kt index 078e92f4243..b0c474ab11b 100644 --- a/compiler/testData/codegen/box/innerNested/passingOuterRef.kt +++ b/compiler/testData/codegen/box/innerNested/passingOuterRef.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR open class A1(y: String) { val x = "A1.x,$y" } @@ -45,4 +44,4 @@ fun box(): String { if (r2 != "A1.x,B1.param,q;A3.x,B2.param,w;A1.x,B1.param,B3.param,e;A3.x,d") return "fail2: $r2" return "OK" -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/box/innerNested/superConstructorCall/deepInnerHierarchy.kt b/compiler/testData/codegen/box/innerNested/superConstructorCall/deepInnerHierarchy.kt index 03c2959605a..08efa14a7ff 100644 --- a/compiler/testData/codegen/box/innerNested/superConstructorCall/deepInnerHierarchy.kt +++ b/compiler/testData/codegen/box/innerNested/superConstructorCall/deepInnerHierarchy.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR open class A(val s: String) { open inner class B(s: String): A(s) diff --git a/compiler/testData/codegen/box/innerNested/superConstructorCall/innerExtendsInnerViaSecondaryConstuctor.kt b/compiler/testData/codegen/box/innerNested/superConstructorCall/innerExtendsInnerViaSecondaryConstuctor.kt index d88b7707f00..971d1a07831 100644 --- a/compiler/testData/codegen/box/innerNested/superConstructorCall/innerExtendsInnerViaSecondaryConstuctor.kt +++ b/compiler/testData/codegen/box/innerNested/superConstructorCall/innerExtendsInnerViaSecondaryConstuctor.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR open class Father(val param: String) { abstract inner class InClass { fun work(): String { @@ -15,4 +14,4 @@ open class Father(val param: String) { fun box(): String { return Father("fail").Child("OK").Child2().work() -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/box/innerNested/superConstructorCall/innerExtendsInnerWithProperOuterCapture.kt b/compiler/testData/codegen/box/innerNested/superConstructorCall/innerExtendsInnerWithProperOuterCapture.kt index 3b74738c140..117f4bf0471 100644 --- a/compiler/testData/codegen/box/innerNested/superConstructorCall/innerExtendsInnerWithProperOuterCapture.kt +++ b/compiler/testData/codegen/box/innerNested/superConstructorCall/innerExtendsInnerWithProperOuterCapture.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR open class Father(val param: String) { abstract inner class InClass { fun work(): String { @@ -15,4 +14,4 @@ open class Father(val param: String) { fun box(): String { return Father("fail").Child("OK").Child2().work() -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/box/localClasses/innerOfLocalCaptureExtensionReceiver.kt b/compiler/testData/codegen/box/localClasses/innerOfLocalCaptureExtensionReceiver.kt index 9d55a96033d..ba3a0df632a 100644 --- a/compiler/testData/codegen/box/localClasses/innerOfLocalCaptureExtensionReceiver.kt +++ b/compiler/testData/codegen/box/localClasses/innerOfLocalCaptureExtensionReceiver.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR fun String.bar(): String { open class Local { fun result() = this@bar diff --git a/compiler/testData/codegen/box/secondaryConstructors/innerClasses.kt b/compiler/testData/codegen/box/secondaryConstructors/innerClasses.kt index e19fc037b7a..9d0851c426b 100644 --- a/compiler/testData/codegen/box/secondaryConstructors/innerClasses.kt +++ b/compiler/testData/codegen/box/secondaryConstructors/innerClasses.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR class Outer { val outerProp: String constructor(x: String) { diff --git a/compiler/testData/codegen/box/secondaryConstructors/innerClassesInheritance.kt b/compiler/testData/codegen/box/secondaryConstructors/innerClassesInheritance.kt index bfe9e2e4477..f68b538d5ef 100644 --- a/compiler/testData/codegen/box/secondaryConstructors/innerClassesInheritance.kt +++ b/compiler/testData/codegen/box/secondaryConstructors/innerClassesInheritance.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR class Outer { val outerProp: String constructor(x: String) { diff --git a/compiler/testData/codegen/box/typealias/innerClassTypeAliasConstructorInSupertypes.kt b/compiler/testData/codegen/box/typealias/innerClassTypeAliasConstructorInSupertypes.kt index a55ab087012..69638e0c6e3 100644 --- a/compiler/testData/codegen/box/typealias/innerClassTypeAliasConstructorInSupertypes.kt +++ b/compiler/testData/codegen/box/typealias/innerClassTypeAliasConstructorInSupertypes.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR class Outer(val x: String) { abstract inner class InnerBase @@ -10,4 +9,4 @@ class Outer(val x: String) { typealias OIB = Outer.InnerBase fun box(): String = - Outer("O").Inner("K").z \ No newline at end of file + Outer("O").Inner("K").z