diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt index d086176a249..959311f0ee8 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt @@ -263,7 +263,11 @@ class GenerationState private constructor( val disableOptimization = configuration.get(JVMConfigurationKeys.DISABLE_OPTIMIZATION, false) - val metadataVersion = configuration.get(CommonConfigurationKeys.METADATA_VERSION) ?: JvmMetadataVersion.INSTANCE + val metadataVersion = + configuration.get(CommonConfigurationKeys.METADATA_VERSION) + ?: if (languageVersionSettings.languageVersion >= LanguageVersion.LATEST_STABLE) JvmMetadataVersion.INSTANCE + else JvmMetadataVersion(1, 1, 18) + val isIrWithStableAbi = configuration.getBoolean(JVMConfigurationKeys.IS_IR_WITH_STABLE_ABI) val globalSerializationBindings = JvmSerializationBindings() diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/metadataVersionDerivedFromLanguage/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/metadataVersionDerivedFromLanguage/source.kt new file mode 100644 index 00000000000..668b01f638e --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/metadataVersionDerivedFromLanguage/source.kt @@ -0,0 +1,3 @@ +class Foo + +fun bar() {} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst14/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst13/library/a.kt similarity index 100% rename from compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst14/library/a.kt rename to compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst13/library/a.kt diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst14/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst13/output.txt similarity index 72% rename from compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst14/output.txt rename to compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst13/output.txt index bb6546a03bb..b08bc1461de 100644 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst14/output.txt +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst13/output.txt @@ -1,7 +1,7 @@ -compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst14/source.kt:3:19: error: 'Nested' is only available since Kotlin 1.44 and cannot be used in Kotlin 1.4 +compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst13/source.kt:3:19: error: 'Nested' is only available since Kotlin 1.44 and cannot be used in Kotlin 1.4 fun test(a: Outer.Nested) { ^ -compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst14/source.kt:4:7: error: 'f(): Unit' is only available since Kotlin 1.88 and cannot be used in Kotlin 1.4 +compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst13/source.kt:4:7: error: 'f(): Unit' is only available since Kotlin 1.88 and cannot be used in Kotlin 1.4 a.f() ^ COMPILATION_ERROR diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst14/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst13/source.kt similarity index 100% rename from compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst14/source.kt rename to compiler/testData/compileKotlinAgainstCustomBinaries/requireKotlinInNestedClassesAgainst13/source.kt diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/strictMetadataVersionSemanticsOldVersion/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/strictMetadataVersionSemanticsOldVersion/output.txt index a8c7b87f739..45fe2dc4d3c 100644 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/strictMetadataVersionSemanticsOldVersion/output.txt +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/strictMetadataVersionSemanticsOldVersion/output.txt @@ -1,6 +1,6 @@ error: incompatible classes were found in dependencies. Remove them from the classpath or use '-Xskip-metadata-version-check' to suppress errors -$TMP_DIR$/library.jar!/META-INF/main.kotlin_module: error: module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.4.0, expected version is $ABI_VERSION$. -compiler/testData/compileKotlinAgainstCustomBinaries/strictMetadataVersionSemanticsOldVersion/source.kt:3:13: error: class 'a.C' was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.4.0, expected version is $ABI_VERSION$. +$TMP_DIR$/library.jar!/META-INF/main.kotlin_module: error: module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.5.0, expected version is $ABI_VERSION$. +compiler/testData/compileKotlinAgainstCustomBinaries/strictMetadataVersionSemanticsOldVersion/source.kt:3:13: error: class 'a.C' was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.5.0, expected version is $ABI_VERSION$. The class is loaded from $TMP_DIR$/library.jar!/a/C.class fun test(c: C) { ^ @@ -10,15 +10,15 @@ compiler/testData/compileKotlinAgainstCustomBinaries/strictMetadataVersionSemant compiler/testData/compileKotlinAgainstCustomBinaries/strictMetadataVersionSemanticsOldVersion/source.kt:5:5: error: unresolved reference: v v ^ -compiler/testData/compileKotlinAgainstCustomBinaries/strictMetadataVersionSemanticsOldVersion/source.kt:6:5: error: class 'a.C' was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.4.0, expected version is $ABI_VERSION$. +compiler/testData/compileKotlinAgainstCustomBinaries/strictMetadataVersionSemanticsOldVersion/source.kt:6:5: error: class 'a.C' was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.5.0, expected version is $ABI_VERSION$. The class is loaded from $TMP_DIR$/library.jar!/a/C.class c.let { C() } ^ -compiler/testData/compileKotlinAgainstCustomBinaries/strictMetadataVersionSemanticsOldVersion/source.kt:6:7: error: class 'a.C' was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.4.0, expected version is $ABI_VERSION$. +compiler/testData/compileKotlinAgainstCustomBinaries/strictMetadataVersionSemanticsOldVersion/source.kt:6:7: error: class 'a.C' was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.5.0, expected version is $ABI_VERSION$. The class is loaded from $TMP_DIR$/library.jar!/a/C.class c.let { C() } ^ -compiler/testData/compileKotlinAgainstCustomBinaries/strictMetadataVersionSemanticsOldVersion/source.kt:6:13: error: class 'a.C' was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.4.0, expected version is $ABI_VERSION$. +compiler/testData/compileKotlinAgainstCustomBinaries/strictMetadataVersionSemanticsOldVersion/source.kt:6:13: error: class 'a.C' was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.5.0, expected version is $ABI_VERSION$. The class is loaded from $TMP_DIR$/library.jar!/a/C.class c.let { C() } ^ diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt index 85a57f0a32b..db60322a569 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt @@ -26,7 +26,10 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion.TEST_IS_PRE_RELEASE_SYS import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.PackageViewDescriptor +import org.jetbrains.kotlin.incremental.LocalFileKotlinClass import org.jetbrains.kotlin.load.java.JvmAnnotationNames +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion +import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils.isObject import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil @@ -39,6 +42,8 @@ import org.jetbrains.org.objectweb.asm.* import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode import org.jetbrains.org.objectweb.asm.tree.MethodNode +import java.io.ByteArrayInputStream +import java.io.DataInputStream import java.io.File import java.net.URLClassLoader import java.util.jar.JarEntry @@ -364,8 +369,8 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration compileKotlin("source.kt", File(tmpdir, "usage.js"), listOf(compileJsLibrary("library")), K2JSCompiler()) } - fun testRequireKotlinInNestedClassesAgainst14() { - val library = compileLibrary("library", additionalOptions = listOf("-Xmetadata-version=1.4.0")) + fun testRequireKotlinInNestedClassesAgainst13() { + val library = compileLibrary("library", additionalOptions = listOf("-language-version", "1.3")) compileKotlin("source.kt", tmpdir, listOf(library)) } @@ -384,11 +389,23 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration fun testStrictMetadataVersionSemanticsOldVersion() { val library = compileLibrary( - "library", additionalOptions = listOf("-Xgenerate-strict-metadata-version", "-Xmetadata-version=1.4.0") + "library", additionalOptions = listOf("-Xgenerate-strict-metadata-version", "-Xmetadata-version=1.5.0") ) compileKotlin("source.kt", tmpdir, listOf(library)) } + fun testMetadataVersionDerivedFromLanguage() { + compileKotlin("source.kt", tmpdir, additionalOptions = listOf("-language-version", "1.3"), expectedFileName = null) + + val expectedVersion = JvmMetadataVersion(1, 1, 18) + val topLevelClass = LocalFileKotlinClass.create(File(tmpdir.absolutePath, "Foo.class"))!! + assertEquals(expectedVersion, topLevelClass.classHeader.metadataVersion) + + val moduleFile = File(tmpdir.absolutePath, "META-INF/main.kotlin_module").readBytes() + val versionNumber = ModuleMapping.readVersionNumber(DataInputStream(ByteArrayInputStream(moduleFile)))!! + assertEquals(expectedVersion, JvmMetadataVersion(*versionNumber)) + } + /*test source mapping generation when source info is absent*/ fun testInlineFunWithoutDebugInfo() { compileKotlin("sourceInline.kt", tmpdir) diff --git a/core/metadata.jvm/src/org/jetbrains/kotlin/metadata/jvm/deserialization/JvmMetadataVersion.kt b/core/metadata.jvm/src/org/jetbrains/kotlin/metadata/jvm/deserialization/JvmMetadataVersion.kt index acc75cfc0e0..d5fae35c55b 100644 --- a/core/metadata.jvm/src/org/jetbrains/kotlin/metadata/jvm/deserialization/JvmMetadataVersion.kt +++ b/core/metadata.jvm/src/org/jetbrains/kotlin/metadata/jvm/deserialization/JvmMetadataVersion.kt @@ -20,14 +20,13 @@ class JvmMetadataVersion(versionArray: IntArray, val isStrictSemantics: Boolean) if (isStrictSemantics) { isCompatibleTo(INSTANCE) } else { - // In Kotlin 1.4, JVM metadata version is going to be advanced to 1.4.0. - // Kotlin 1.3 is able to read metadata of versions up to Kotlin 1.4 (unless the version has strict semantics). - major == 1 && minor <= 4 + // Kotlin 1.N is able to read metadata of versions up to Kotlin 1.{N+1} (unless the version has strict semantics). + major == INSTANCE.major && minor <= INSTANCE.minor + 1 } companion object { @JvmField - val INSTANCE = JvmMetadataVersion(1, 1, 17) + val INSTANCE = JvmMetadataVersion(1, 4, 0) @JvmField val INVALID_VERSION = JvmMetadataVersion() diff --git a/core/metadata.jvm/src/org/jetbrains/kotlin/metadata/jvm/deserialization/ModuleMapping.kt b/core/metadata.jvm/src/org/jetbrains/kotlin/metadata/jvm/deserialization/ModuleMapping.kt index 1ccc216013d..69b12a2f79d 100644 --- a/core/metadata.jvm/src/org/jetbrains/kotlin/metadata/jvm/deserialization/ModuleMapping.kt +++ b/core/metadata.jvm/src/org/jetbrains/kotlin/metadata/jvm/deserialization/ModuleMapping.kt @@ -33,12 +33,19 @@ class ModuleMapping private constructor( const val STRICT_METADATA_VERSION_SEMANTICS_FLAG = 1 shl 0 + fun readVersionNumber(stream: DataInputStream): IntArray? = + try { + IntArray(stream.readInt()) { stream.readInt() } + } catch (e: IOException) { + null + } + fun loadModuleMapping( bytes: ByteArray?, debugName: String, skipMetadataVersionCheck: Boolean, isJvmPackageNameSupported: Boolean, - reportIncompatibleVersionError: (JvmMetadataVersion) -> Unit + reportIncompatibleVersionError: (JvmMetadataVersion) -> Unit, ): ModuleMapping { if (bytes == null) { return EMPTY @@ -46,12 +53,7 @@ class ModuleMapping private constructor( val stream = DataInputStream(ByteArrayInputStream(bytes)) - val versionNumber = try { - IntArray(stream.readInt()) { stream.readInt() } - } catch (e: IOException) { - return CORRUPTED - } - + val versionNumber = readVersionNumber(stream) ?: return CORRUPTED val preVersion = JvmMetadataVersion(*versionNumber) if (!skipMetadataVersionCheck && !preVersion.isCompatible()) { reportIncompatibleVersionError(preVersion)