From 4973baae4ee08e5c099b2c43df97ab75ecd432cb Mon Sep 17 00:00:00 2001 From: Kristoffer Andersen Date: Mon, 11 Nov 2019 13:25:26 +0100 Subject: [PATCH] [JVM IR] Fix JvmOverloads+Parameterless Main Resolves the interaction of @JvmOverloads annotations and parameterless main methods. In the following code, both mechanisms generate methods that ultimately produce the signature `public static void main(String[] args)` of which there can be only one (true in general of any signature). ``` fun main() { } @JvmOverloads fun main(Array args, x: Int = 42) { } ``` This PR simply shuffles the lowerings around, letting parameterless main methods detect the presence of the default overload produced by the annotation. Additionally, this PR improves the testing of parameterless main methods by actual bytecode patterns, and not simple check for successful compilation (as @sfs and I discovered, there are issues in flagging an error on duplicate signatures on the IR backend). --- .../src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt | 9 ++------- .../backend/jvm/lower/MainMethodGenerationLowering.kt | 8 ++++++++ .../parameterlessMain/dontGenerateOnJvmNameMain.kt | 4 +++- .../parameterlessMain/dontGenerateOnJvmOverloads.kt | 11 +++++++++++ .../parameterlessMain/dontGenerateOnMain.kt | 4 +++- .../parameterlessMain/dontGenerateOnMainExtension.kt | 4 +++- .../parameterlessMain/dontGenerateOnNullableArray.kt | 4 +++- .../parameterlessMain/dontGenerateOnVarargsString.kt | 9 +++++++++ .../kotlin/codegen/BytecodeTextTestGenerated.java | 10 ++++++++++ .../codegen/ir/IrBytecodeTextTestGenerated.java | 10 ++++++++++ 10 files changed, 62 insertions(+), 11 deletions(-) create mode 100644 compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnJvmOverloads.kt create mode 100644 compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnVarargsString.kt diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 8388bea7023..5cfb6806d9f 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -210,15 +210,8 @@ private val syntheticAccessorPhase = makeIrFilePhase( prerequisite = setOf(objectClassPhase, staticDefaultFunctionPhase, interfacePhase) ) -private val mainMethodGenerationPhase = makeIrFilePhase( - ::MainMethodGenerationLowering, - name = "MainMethodGeneration", - description = "Identify parameterless main methods and generate bridge main-methods" -) - @Suppress("Reformat") private val jvmFilePhases = - mainMethodGenerationPhase then typeAliasAnnotationMethodsPhase then stripTypeAliasDeclarationsPhase then provisionalFunctionExpressionPhase then @@ -299,6 +292,8 @@ private val jvmFilePhases = checkLocalNamesWithOldBackendPhase then + mainMethodGenerationPhase then + // should be last transformation removeDeclarationsThatWouldBeInlined then makePatchParentsPhase(3) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MainMethodGenerationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MainMethodGenerationLowering.kt index 60f99c0105a..8d0c3acdeb8 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MainMethodGenerationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MainMethodGenerationLowering.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.ir.allParameters import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.ir.getJvmNameFromAnnotation @@ -28,6 +29,13 @@ import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.Variance +internal val mainMethodGenerationPhase = makeIrFilePhase( + ::MainMethodGenerationLowering, + name = "MainMethodGeneration", + description = "Identify parameterless main methods and generate bridge main-methods", + prerequisite = setOf(jvmOverloadsAnnotationPhase) +) + internal class MainMethodGenerationLowering(val context: JvmBackendContext) : ClassLoweringPass { override fun lower(irClass: IrClass) { diff --git a/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnJvmNameMain.kt b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnJvmNameMain.kt index 3b5d9bffb4e..fe347899827 100644 --- a/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnJvmNameMain.kt +++ b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnJvmNameMain.kt @@ -5,4 +5,6 @@ fun main() { @JvmName("main") fun foo(args: Array) { -} \ No newline at end of file +} + +// 0 INVOKESTATIC DontGenerateOnJvmNameMainKt\.main ()V \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnJvmOverloads.kt b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnJvmOverloads.kt new file mode 100644 index 00000000000..002bd0f8b41 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnJvmOverloads.kt @@ -0,0 +1,11 @@ +// IGNORE_BACKEND: JVM +fun main() { + println("FAIL") +} + +@JvmOverloads +fun Array.main(x: Int = 4, y: String = "Test") { + println("OK") +} + +// 0 INVOKESTATIC DontGenerateOnJvmOverloadsKt\.main ()V \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMain.kt b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMain.kt index 04e40fe1209..804788c8e31 100644 --- a/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMain.kt +++ b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMain.kt @@ -4,4 +4,6 @@ fun main() { fun main(args: Array) { -} \ No newline at end of file +} + +// 0 INVOKESTATIC DontGenerateOnMainKt\.main ()V \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMainExtension.kt b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMainExtension.kt index d5123b42bdc..69158538cb8 100644 --- a/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMainExtension.kt +++ b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMainExtension.kt @@ -4,4 +4,6 @@ fun main() { fun Array.main() { -} \ No newline at end of file +} + +// 0 INVOKESTATIC DontGenerateOnMainExtensionKt\.main ()V \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnNullableArray.kt b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnNullableArray.kt index fdf3af46276..6dabd934994 100644 --- a/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnNullableArray.kt +++ b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnNullableArray.kt @@ -4,4 +4,6 @@ fun main() { fun main(args: Array?) { -} \ No newline at end of file +} + +// 0 INVOKESTATIC DontGenerateOnNullableArrayKt\.main ()V \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnVarargsString.kt b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnVarargsString.kt new file mode 100644 index 00000000000..94cc54a4896 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnVarargsString.kt @@ -0,0 +1,9 @@ +fun main() { + +} + +fun main(vararg args: String) { + +} + +// 0 INVOKESTATIC DontGenerateOnVarargsStringKt\.main ()V \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 8e6874bb5bc..0b6ac8a02ce 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -3545,6 +3545,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnJvmNameMain.kt"); } + @TestMetadata("dontGenerateOnJvmOverloads.kt") + public void testDontGenerateOnJvmOverloads() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnJvmOverloads.kt"); + } + @TestMetadata("dontGenerateOnMain.kt") public void testDontGenerateOnMain() throws Exception { runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMain.kt"); @@ -3559,6 +3564,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { public void testDontGenerateOnNullableArray() throws Exception { runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnNullableArray.kt"); } + + @TestMetadata("dontGenerateOnVarargsString.kt") + public void testDontGenerateOnVarargsString() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnVarargsString.kt"); + } } @TestMetadata("compiler/testData/codegen/bytecodeText/properties") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java index 0b0531caf42..1b2bb8f1052 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java @@ -3463,6 +3463,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnJvmNameMain.kt"); } + @TestMetadata("dontGenerateOnJvmOverloads.kt") + public void testDontGenerateOnJvmOverloads() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnJvmOverloads.kt"); + } + @TestMetadata("dontGenerateOnMain.kt") public void testDontGenerateOnMain() throws Exception { runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMain.kt"); @@ -3477,6 +3482,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { public void testDontGenerateOnNullableArray() throws Exception { runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnNullableArray.kt"); } + + @TestMetadata("dontGenerateOnVarargsString.kt") + public void testDontGenerateOnVarargsString() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnVarargsString.kt"); + } } @TestMetadata("compiler/testData/codegen/bytecodeText/properties")