JVM IR: sanitize indy lambda proxy names correctly
In case there are several proxy functions for indy lambdas in the same container, its names are "...__proxy", "...__proxy-0", "...__proxy-1", ..., yet before this change, only the first one was sanitized. So if it's happening inside a constructor, `<init>` was left unrenamed which led to ClassFormatError. #KT-52040 Fixed
This commit is contained in:
+6
@@ -25996,6 +25996,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/kt47510.kt");
|
runTest("compiler/testData/codegen/box/invokedynamic/sam/kt47510.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt52040_severalProxyFunsInInit.kt")
|
||||||
|
public void testKt52040_severalProxyFunsInInit() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/sam/kt52040_severalProxyFunsInInit.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("nullabilityAssertions.kt")
|
@TestMetadata("nullabilityAssertions.kt")
|
||||||
public void testNullabilityAssertions() throws Exception {
|
public void testNullabilityAssertions() throws Exception {
|
||||||
|
|||||||
+5
-13
@@ -33,15 +33,6 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
interface LocalNameProvider {
|
|
||||||
fun localName(declaration: IrDeclarationWithName): String =
|
|
||||||
declaration.name.asString()
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val DEFAULT = object : LocalNameProvider {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface VisibilityPolicy {
|
interface VisibilityPolicy {
|
||||||
fun forClass(declaration: IrClass, inInlineFunctionScope: Boolean): DescriptorVisibility =
|
fun forClass(declaration: IrClass, inInlineFunctionScope: Boolean): DescriptorVisibility =
|
||||||
declaration.visibility
|
declaration.visibility
|
||||||
@@ -77,7 +68,7 @@ object BOUND_RECEIVER_PARAMETER : IrDeclarationOriginImpl("BOUND_RECEIVER_PARAME
|
|||||||
*/
|
*/
|
||||||
class LocalDeclarationsLowering(
|
class LocalDeclarationsLowering(
|
||||||
val context: CommonBackendContext,
|
val context: CommonBackendContext,
|
||||||
val localNameProvider: LocalNameProvider = LocalNameProvider.DEFAULT,
|
val localNameSanitizer: (String) -> String = { it },
|
||||||
val visibilityPolicy: VisibilityPolicy = VisibilityPolicy.DEFAULT,
|
val visibilityPolicy: VisibilityPolicy = VisibilityPolicy.DEFAULT,
|
||||||
val suggestUniqueNames: Boolean = true, // When `true` appends a `-#index` suffix to lifted declaration names
|
val suggestUniqueNames: Boolean = true, // When `true` appends a `-#index` suffix to lifted declaration names
|
||||||
val forceFieldsForInlineCaptures: Boolean = false // See `LocalClassContext`
|
val forceFieldsForInlineCaptures: Boolean = false // See `LocalClassContext`
|
||||||
@@ -594,13 +585,14 @@ class LocalDeclarationsLowering(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun suggestLocalName(declaration: IrDeclarationWithName): String {
|
private fun suggestLocalName(declaration: IrDeclarationWithName): String {
|
||||||
|
val declarationName = localNameSanitizer(declaration.name.asString())
|
||||||
localFunctions[declaration]?.let {
|
localFunctions[declaration]?.let {
|
||||||
val baseName = if (declaration.name.isSpecial) "lambda" else declaration.name
|
val baseName = if (declaration.name.isSpecial) "lambda" else declarationName
|
||||||
if (it.index >= 0)
|
if (it.index >= 0)
|
||||||
return if (suggestUniqueNames) "$baseName-${it.index}" else "$baseName"
|
return if (suggestUniqueNames) "$baseName-${it.index}" else baseName
|
||||||
}
|
}
|
||||||
|
|
||||||
return localNameProvider.localName(declaration)
|
return declarationName
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateNameForLiftedDeclaration(
|
private fun generateNameForLiftedDeclaration(
|
||||||
|
|||||||
@@ -116,10 +116,7 @@ internal val localDeclarationsPhase = makeIrFilePhase(
|
|||||||
{ context ->
|
{ context ->
|
||||||
LocalDeclarationsLowering(
|
LocalDeclarationsLowering(
|
||||||
context,
|
context,
|
||||||
object : LocalNameProvider {
|
NameUtils::sanitizeAsJavaIdentifier,
|
||||||
override fun localName(declaration: IrDeclarationWithName): String =
|
|
||||||
NameUtils.sanitizeAsJavaIdentifier(super.localName(declaration))
|
|
||||||
},
|
|
||||||
object : VisibilityPolicy {
|
object : VisibilityPolicy {
|
||||||
// Note: any condition that results in non-`LOCAL` visibility here should be duplicated in `JvmLocalClassPopupLowering`,
|
// Note: any condition that results in non-`LOCAL` visibility here should be duplicated in `JvmLocalClassPopupLowering`,
|
||||||
// else it won't detect the class as local.
|
// else it won't detect the class as local.
|
||||||
|
|||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// FULL_JDK
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// FILE: J.java
|
||||||
|
|
||||||
|
import java.util.function.*;
|
||||||
|
|
||||||
|
public class J {
|
||||||
|
public static String f1(Supplier<Object> r) {
|
||||||
|
r.get();
|
||||||
|
return "O";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String f2(Supplier<Object> r) {
|
||||||
|
r.get();
|
||||||
|
return "K";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
|
||||||
|
class C private constructor() {
|
||||||
|
companion object {
|
||||||
|
fun x1() = J.f1(::C)
|
||||||
|
fun x2() = J.f2(::C)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String = C.x1() + C.x2()
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// FULL_JDK
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// FILE: J.java
|
||||||
|
|
||||||
|
import java.util.function.*;
|
||||||
|
|
||||||
|
public class J {
|
||||||
|
public static void f1(Supplier<Object> r) {}
|
||||||
|
public static void f2(Supplier<Object> r) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
|
||||||
|
class C private constructor() {
|
||||||
|
companion object {
|
||||||
|
fun x1() = J.f1(::C)
|
||||||
|
fun x2() = J.f2(::C)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
synthetic final class C$Companion$x1$1 {
|
||||||
|
// source: 'test.kt'
|
||||||
|
enclosing method C$Companion.x1()V
|
||||||
|
public final static field INSTANCE: C$Companion$x1$1
|
||||||
|
inner (anonymous) class C$Companion$x1$1
|
||||||
|
static method <clinit>(): void
|
||||||
|
method <init>(): void
|
||||||
|
public final @org.jetbrains.annotations.NotNull method invoke(): C
|
||||||
|
public synthetic bridge method invoke(): java.lang.Object
|
||||||
|
public final inner class C$Companion
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
synthetic final class C$Companion$x2$1 {
|
||||||
|
// source: 'test.kt'
|
||||||
|
enclosing method C$Companion.x2()V
|
||||||
|
public final static field INSTANCE: C$Companion$x2$1
|
||||||
|
inner (anonymous) class C$Companion$x2$1
|
||||||
|
static method <clinit>(): void
|
||||||
|
method <init>(): void
|
||||||
|
public final @org.jetbrains.annotations.NotNull method invoke(): C
|
||||||
|
public synthetic bridge method invoke(): java.lang.Object
|
||||||
|
public final inner class C$Companion
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class C$Companion {
|
||||||
|
// source: 'test.kt'
|
||||||
|
inner (anonymous) class C$Companion$x1$1
|
||||||
|
inner (anonymous) class C$Companion$x2$1
|
||||||
|
inner (anonymous) class C$sam$java_util_function_Supplier$0
|
||||||
|
private method <init>(): void
|
||||||
|
public synthetic method <init>(p0: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||||
|
public final method x1(): void
|
||||||
|
public final method x2(): void
|
||||||
|
public final inner class C$Companion
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
synthetic final class C$sam$java_util_function_Supplier$0 {
|
||||||
|
// source: 'test.kt'
|
||||||
|
enclosing method C$Companion.x1()V
|
||||||
|
private synthetic final field function: kotlin.jvm.functions.Function0
|
||||||
|
inner (anonymous) class C$sam$java_util_function_Supplier$0
|
||||||
|
method <init>(p0: kotlin.jvm.functions.Function0): void
|
||||||
|
public synthetic final method get(): java.lang.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class C {
|
||||||
|
// source: 'test.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull field Companion: C$Companion
|
||||||
|
static method <clinit>(): void
|
||||||
|
private method <init>(): void
|
||||||
|
public synthetic method <init>(p0: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||||
|
public final inner class C$Companion
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class C$Companion {
|
||||||
|
// source: 'test.kt'
|
||||||
|
private method <init>(): void
|
||||||
|
public synthetic method <init>(p0: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||||
|
private synthetic final static method x1$_init___proxy(): C
|
||||||
|
public final method x1(): void
|
||||||
|
private synthetic final static method x2$_init___proxy-0(): C
|
||||||
|
public final method x2(): void
|
||||||
|
public final inner class C$Companion
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class C {
|
||||||
|
// source: 'test.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull field Companion: C$Companion
|
||||||
|
static method <clinit>(): void
|
||||||
|
private method <init>(): void
|
||||||
|
public synthetic method <init>(p0: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||||
|
public final inner class C$Companion
|
||||||
|
}
|
||||||
+6
@@ -25540,6 +25540,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/kt47510.kt");
|
runTest("compiler/testData/codegen/box/invokedynamic/sam/kt47510.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt52040_severalProxyFunsInInit.kt")
|
||||||
|
public void testKt52040_severalProxyFunsInInit() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/sam/kt52040_severalProxyFunsInInit.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("nullabilityAssertions.kt")
|
@TestMetadata("nullabilityAssertions.kt")
|
||||||
public void testNullabilityAssertions() throws Exception {
|
public void testNullabilityAssertions() throws Exception {
|
||||||
|
|||||||
+6
@@ -2146,6 +2146,12 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeListing/sam/samAdapterInInlineLambda.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/sam/samAdapterInInlineLambda.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("severalProxyFunsInInit.kt")
|
||||||
|
public void testSeveralProxyFunsInInit() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/sam/severalProxyFunsInInit.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("specializedFunInterface.kt")
|
@TestMetadata("specializedFunInterface.kt")
|
||||||
public void testSpecializedFunInterface() throws Exception {
|
public void testSpecializedFunInterface() throws Exception {
|
||||||
|
|||||||
+6
@@ -25996,6 +25996,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/kt47510.kt");
|
runTest("compiler/testData/codegen/box/invokedynamic/sam/kt47510.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt52040_severalProxyFunsInInit.kt")
|
||||||
|
public void testKt52040_severalProxyFunsInInit() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/sam/kt52040_severalProxyFunsInInit.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("nullabilityAssertions.kt")
|
@TestMetadata("nullabilityAssertions.kt")
|
||||||
public void testNullabilityAssertions() throws Exception {
|
public void testNullabilityAssertions() throws Exception {
|
||||||
|
|||||||
+6
@@ -2242,6 +2242,12 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
|
|||||||
runTest("compiler/testData/codegen/bytecodeListing/sam/samAdapterInInlineLambda.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/sam/samAdapterInInlineLambda.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("severalProxyFunsInInit.kt")
|
||||||
|
public void testSeveralProxyFunsInInit() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/sam/severalProxyFunsInInit.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("specializedFunInterface.kt")
|
@TestMetadata("specializedFunInterface.kt")
|
||||||
public void testSpecializedFunInterface() throws Exception {
|
public void testSpecializedFunInterface() throws Exception {
|
||||||
|
|||||||
+5
@@ -21506,6 +21506,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/kt47510.kt");
|
runTest("compiler/testData/codegen/box/invokedynamic/sam/kt47510.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt52040_severalProxyFunsInInit.kt")
|
||||||
|
public void testKt52040_severalProxyFunsInInit() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/sam/kt52040_severalProxyFunsInInit.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("nullabilityAssertions.kt")
|
@TestMetadata("nullabilityAssertions.kt")
|
||||||
public void testNullabilityAssertions() throws Exception {
|
public void testNullabilityAssertions() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/nullabilityAssertions.kt");
|
runTest("compiler/testData/codegen/box/invokedynamic/sam/nullabilityAssertions.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user