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 ed57f52192a..f24b29deb7a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods import org.jetbrains.kotlin.codegen.optimization.OptimizationClassBuilderFactory import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings import org.jetbrains.kotlin.config.* +import org.jetbrains.kotlin.config.LanguageVersion.* import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ScriptDescriptor @@ -49,6 +50,7 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeApproximator import org.jetbrains.org.objectweb.asm.Type import java.io.File +import java.util.* class GenerationState private constructor( val project: Project, @@ -320,8 +322,7 @@ class GenerationState private constructor( val metadataVersion = configuration.get(CommonConfigurationKeys.METADATA_VERSION) - ?: if (languageVersionSettings.languageVersion >= LanguageVersion.LATEST_STABLE) JvmMetadataVersion.INSTANCE - else JvmMetadataVersion(1, 1, 18) + ?: LANGUAGE_TO_METADATA_VERSION.getValue(languageVersionSettings.languageVersion) val abiStability = configuration.get(JVMConfigurationKeys.ABI_STABILITY) @@ -392,6 +393,24 @@ class GenerationState private constructor( private fun shouldOnlyCollectSignatures(origin: JvmDeclarationOrigin) = classBuilderMode == ClassBuilderMode.LIGHT_CLASSES && origin.originKind in doNotGenerateInLightClassMode + + companion object { + private val LANGUAGE_TO_METADATA_VERSION = EnumMap(LanguageVersion::class.java).apply { + val oldMetadataVersion = JvmMetadataVersion(1, 1, 18) + this[KOTLIN_1_0] = oldMetadataVersion + this[KOTLIN_1_1] = oldMetadataVersion + this[KOTLIN_1_2] = oldMetadataVersion + this[KOTLIN_1_3] = oldMetadataVersion + this[KOTLIN_1_4] = JvmMetadataVersion(1, 4, 3) + this[KOTLIN_1_5] = JvmMetadataVersion.INSTANCE + this[KOTLIN_1_6] = JvmMetadataVersion(1, 6, 0) + + check(size == LanguageVersion.values().size) { + "Please add mappings from the missing LanguageVersion instances to the corresponding JvmMetadataVersion " + + "in `GenerationState.LANGUAGE_TO_METADATA_VERSION`" + } + } + } } private val doNotGenerateInLightClassMode = setOf(CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL, BRIDGE, COLLECTION_STUB, AUGMENTED_BUILTIN_API) diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/strictMetadataVersionSemanticsOldVersion/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/strictMetadataVersionSemanticsOldVersion/output.txt index 45fe2dc4d3c..516d02f626e 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.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$. +$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.6.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.6.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.5.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.6.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.5.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.6.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.5.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.6.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 8b4940a5851..4eaf74593c2 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt @@ -421,22 +421,38 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration } fun testStrictMetadataVersionSemanticsOldVersion() { + val nextMetadataVersion = JvmMetadataVersion(JvmMetadataVersion.INSTANCE.major, JvmMetadataVersion.INSTANCE.minor + 1, 0) val library = compileLibrary( - "library", additionalOptions = listOf("-Xgenerate-strict-metadata-version", "-Xmetadata-version=1.5.0") + "library", additionalOptions = listOf("-Xgenerate-strict-metadata-version", "-Xmetadata-version=$nextMetadataVersion") ) compileKotlin("source.kt", tmpdir, listOf(library)) } fun testMetadataVersionDerivedFromLanguage() { - compileKotlin("source.kt", tmpdir, additionalOptions = listOf("-language-version", "1.3"), expectedFileName = null) + for (languageVersion in LanguageVersion.values()) { + if (languageVersion.isUnsupported) continue - val expectedVersion = JvmMetadataVersion(1, 1, 18) - val topLevelClass = LocalFileKotlinClass.create(File(tmpdir.absolutePath, "Foo.class"))!! - assertEquals(expectedVersion, topLevelClass.classHeader.metadataVersion) + compileKotlin( + "source.kt", tmpdir, additionalOptions = listOf("-language-version", languageVersion.versionString), + expectedFileName = null + ) - val moduleFile = File(tmpdir.absolutePath, "META-INF/main.kotlin_module").readBytes() - val versionNumber = ModuleMapping.readVersionNumber(DataInputStream(ByteArrayInputStream(moduleFile)))!! - assertEquals(expectedVersion, JvmMetadataVersion(*versionNumber)) + // Starting from Kotlin 1.4, major.minor version of JVM metadata must be equal to the language version. + // From Kotlin 1.0 to 1.4, we used JVM metadata version 1.1.*. + val expectedMajor = 1 + val expectedMinor = if (languageVersion < LanguageVersion.KOTLIN_1_4) 1 else languageVersion.minor + + val topLevelClass = LocalFileKotlinClass.create(File(tmpdir.absolutePath, "Foo.class"))!! + val classVersion = topLevelClass.classHeader.metadataVersion + assertEquals("Actual version: $classVersion", expectedMajor, classVersion.major) + assertEquals("Actual version: $classVersion", expectedMinor, classVersion.minor) + + val moduleFile = File(tmpdir.absolutePath, "META-INF/main.kotlin_module").readBytes() + val versionNumber = ModuleMapping.readVersionNumber(DataInputStream(ByteArrayInputStream(moduleFile)))!! + val moduleVersion = JvmMetadataVersion(*versionNumber) + assertEquals("Actual version: $moduleVersion", expectedMajor, moduleVersion.major) + assertEquals("Actual version: $moduleVersion", expectedMinor, moduleVersion.minor) + } } /*test source mapping generation when source info is absent*/ 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 43e17e0ccdf..1b1ea4deda8 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 @@ -26,7 +26,7 @@ class JvmMetadataVersion(versionArray: IntArray, val isStrictSemantics: Boolean) companion object { @JvmField - val INSTANCE = JvmMetadataVersion(1, 4, 2) + val INSTANCE = JvmMetadataVersion(1, 5, 0) @JvmField val INVALID_VERSION = JvmMetadataVersion() diff --git a/libraries/reflect/build.gradle.kts b/libraries/reflect/build.gradle.kts index edb4652eae9..8c75995d8cb 100644 --- a/libraries/reflect/build.gradle.kts +++ b/libraries/reflect/build.gradle.kts @@ -11,7 +11,7 @@ description = "Kotlin Full Reflection Library" buildscript { dependencies { - classpath("org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0") + classpath("org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.2.0") } } diff --git a/libraries/tools/binary-compatibility-validator/build.gradle b/libraries/tools/binary-compatibility-validator/build.gradle index 63f44f4b56b..584c858ba35 100644 --- a/libraries/tools/binary-compatibility-validator/build.gradle +++ b/libraries/tools/binary-compatibility-validator/build.gradle @@ -6,6 +6,11 @@ configurations { } dependencies { + // Override dependency of binary-compatibility-validator:0.2.3 on kotlinx-metadata-jvm:0.1.0, + // until the new version of the binary compatibility validator is released. + // kotlinx-metadata-jvm 0.1.0 can't read metadata of version 1.5 and greater. + runtimeOnly("org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.2.0") + compile("org.jetbrains.kotlinx:binary-compatibility-validator:0.2.3") testCompile project(':kotlin-test:kotlin-test-junit')