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:
Alexander Udalov
2020-09-03 18:13:03 +02:00
parent 2ab68b3245
commit 228e329d1f
6 changed files with 88 additions and 1 deletions
@@ -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.
(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()}")
return true
@@ -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)
}
@@ -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
}
@@ -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
}
@@ -469,6 +469,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
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")
public void testTransformedConstructor() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/inline/enclosingInfo/transformedConstructor.kt");
@@ -439,6 +439,11 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
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")
public void testTransformedConstructor() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/inline/enclosingInfo/transformedConstructor.kt");