JVM IR: generate enclosing constructor only for lambdas in initializers
There was a typo in JvmLocalClassPopupLowering which allowed the EnclosingMethod for lambdas and anonymous classes in initializers to become any function in a class, in case when there was no primary constructor in that class. E.g. in the added test, `getIrrelevantField` was the EnclosingMethod of the lambda class before this change.
This commit is contained in:
+1
-1
@@ -57,7 +57,7 @@ class JvmLocalClassPopupLowering(context: JvmBackendContext) : LocalClassPopupLo
|
|||||||
|
|
||||||
// In case there's no primary constructor, it's unclear which constructor should be the enclosing one, so we select the first.
|
// In case there's no primary constructor, it's unclear which constructor should be the enclosing one, so we select the first.
|
||||||
(context as JvmBackendContext).customEnclosingFunction[klass.attributeOwnerId] =
|
(context as JvmBackendContext).customEnclosingFunction[klass.attributeOwnerId] =
|
||||||
container.primaryConstructor ?: container.declarations.firstIsInstanceOrNull()
|
container.primaryConstructor ?: container.declarations.firstIsInstanceOrNull<IrConstructor>()
|
||||||
?: error("Class in a non-static initializer found, but container has no constructors: ${container.render()}")
|
?: error("Class in a non-static initializer found, but container has no constructors: ${container.render()}")
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
interface A
|
||||||
|
interface B
|
||||||
|
|
||||||
|
class E {
|
||||||
|
val irrelevantField = 1
|
||||||
|
|
||||||
|
init {
|
||||||
|
// This test checks that EnclosingMethod (named "outer class" in ASM for some reason) of this lambda class contains
|
||||||
|
// something sensible. Currently, we use one of the constructors (not important which).
|
||||||
|
val lambda = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(a: A)
|
||||||
|
constructor(b: B)
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public interface A {
|
||||||
|
// source: 'lambdaInInitBlockNoPrimaryConstructor.kt'
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public interface B {
|
||||||
|
// source: 'lambdaInInitBlockNoPrimaryConstructor.kt'
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
final class E$lambda$1 {
|
||||||
|
// source: 'lambdaInInitBlockNoPrimaryConstructor.kt'
|
||||||
|
enclosing method E.<init>(LB;)V
|
||||||
|
public final static field INSTANCE: E$lambda$1
|
||||||
|
inner (anonymous) class E$lambda$1
|
||||||
|
static method <clinit>(): void
|
||||||
|
method <init>(): void
|
||||||
|
public synthetic bridge method invoke(): java.lang.Object
|
||||||
|
public final method invoke(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class E {
|
||||||
|
// source: 'lambdaInInitBlockNoPrimaryConstructor.kt'
|
||||||
|
private final field irrelevantField: int
|
||||||
|
inner (anonymous) class E$lambda$1
|
||||||
|
public method <init>(@org.jetbrains.annotations.NotNull p0: A): void
|
||||||
|
public method <init>(@org.jetbrains.annotations.NotNull p0: B): void
|
||||||
|
public final method getIrrelevantField(): int
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public interface A {
|
||||||
|
// source: 'lambdaInInitBlockNoPrimaryConstructor.kt'
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public interface B {
|
||||||
|
// source: 'lambdaInInitBlockNoPrimaryConstructor.kt'
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
final class E$lambda$1 {
|
||||||
|
// source: 'lambdaInInitBlockNoPrimaryConstructor.kt'
|
||||||
|
enclosing method E.<init>(LA;)V
|
||||||
|
public final static field INSTANCE: E$lambda$1
|
||||||
|
inner (anonymous) class E$lambda$1
|
||||||
|
static method <clinit>(): void
|
||||||
|
method <init>(): void
|
||||||
|
public synthetic bridge method invoke(): java.lang.Object
|
||||||
|
public final method invoke(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class E {
|
||||||
|
// source: 'lambdaInInitBlockNoPrimaryConstructor.kt'
|
||||||
|
private final field irrelevantField: int
|
||||||
|
inner (anonymous) class E$lambda$1
|
||||||
|
public method <init>(@org.jetbrains.annotations.NotNull p0: A): void
|
||||||
|
public method <init>(@org.jetbrains.annotations.NotNull p0: B): void
|
||||||
|
public final method getIrrelevantField(): int
|
||||||
|
}
|
||||||
+5
@@ -469,6 +469,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeListing/inline/enclosingInfo/kt10259.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/inline/enclosingInfo/kt10259.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("lambdaInInitBlockNoPrimaryConstructor.kt")
|
||||||
|
public void testLambdaInInitBlockNoPrimaryConstructor() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/inline/enclosingInfo/lambdaInInitBlockNoPrimaryConstructor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("transformedConstructor.kt")
|
@TestMetadata("transformedConstructor.kt")
|
||||||
public void testTransformedConstructor() throws Exception {
|
public void testTransformedConstructor() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeListing/inline/enclosingInfo/transformedConstructor.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/inline/enclosingInfo/transformedConstructor.kt");
|
||||||
|
|||||||
+5
@@ -439,6 +439,11 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
|
|||||||
runTest("compiler/testData/codegen/bytecodeListing/inline/enclosingInfo/kt10259.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/inline/enclosingInfo/kt10259.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("lambdaInInitBlockNoPrimaryConstructor.kt")
|
||||||
|
public void testLambdaInInitBlockNoPrimaryConstructor() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/inline/enclosingInfo/lambdaInInitBlockNoPrimaryConstructor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("transformedConstructor.kt")
|
@TestMetadata("transformedConstructor.kt")
|
||||||
public void testTransformedConstructor() throws Exception {
|
public void testTransformedConstructor() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeListing/inline/enclosingInfo/transformedConstructor.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/inline/enclosingInfo/transformedConstructor.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user