Deserialization/class reading: pass chosen JvmMetadataVersion whenever possible
This commit is contained in:
+31
-12
@@ -14,24 +14,43 @@ import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
||||
class JvmMetadataVersion(versionArray: IntArray, val isStrictSemantics: Boolean) : BinaryVersion(*versionArray) {
|
||||
constructor(vararg numbers: Int) : this(numbers, isStrictSemantics = false)
|
||||
|
||||
override fun isCompatibleWithCurrentCompilerVersion(): Boolean =
|
||||
override fun isCompatibleWithCurrentCompilerVersion(): Boolean {
|
||||
return isCompatibleInternal(INSTANCE_NEXT)
|
||||
}
|
||||
|
||||
fun isCompatible(metadataVersionFromLanguageVersion: JvmMetadataVersion): Boolean {
|
||||
// * Compiler of deployVersion X (INSTANCE) with LV Y (metadataVersionFromLanguageVersion)
|
||||
// * can read metadata with version <= max(X+1, Y)
|
||||
val forwardCompatibility = if (isStrictSemantics) INSTANCE else INSTANCE_NEXT
|
||||
val limitVersion = maxOf(forwardCompatibility, metadataVersionFromLanguageVersion)
|
||||
return isCompatibleInternal(limitVersion)
|
||||
}
|
||||
|
||||
private fun isCompatibleInternal(limitVersion: JvmMetadataVersion): Boolean {
|
||||
// NOTE: 1.0 is a pre-Kotlin-1.0 metadata version, with which the current compiler is incompatible
|
||||
(major != 1 || minor != 0) &&
|
||||
if (isStrictSemantics) {
|
||||
isCompatibleTo(INSTANCE)
|
||||
} else {
|
||||
// Kotlin 1.N is able to read metadata of versions up to Kotlin 1.{N+1} (unless the version has strict semantics).
|
||||
// Kotlin 1.9 is able to read Kotlin 2.0
|
||||
// Kotlin K.* is able to read Kotlin M.* if K > M
|
||||
major == INSTANCE.major && minor <= INSTANCE.minor + 1 ||
|
||||
major == 2 && INSTANCE.major == 1 && minor == 9 ||
|
||||
major < INSTANCE.major
|
||||
}
|
||||
if (major == 1 && minor == 0) return false
|
||||
// The same for 0.*
|
||||
if (major == 0) return false
|
||||
// Otherwise we just compare with the given limitVersion
|
||||
return this <= limitVersion
|
||||
}
|
||||
|
||||
fun next(): JvmMetadataVersion {
|
||||
if (minor < 9 || major > 1) return JvmMetadataVersion(major, minor + 1, 0)
|
||||
return JvmMetadataVersion(2, 0, 0)
|
||||
}
|
||||
|
||||
fun prev(): JvmMetadataVersion {
|
||||
if (minor > 0) return JvmMetadataVersion(major, minor - 1, 0)
|
||||
return JvmMetadataVersion(major - 1, 9, 0)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val INSTANCE = JvmMetadataVersion(1, 8, 0)
|
||||
|
||||
private val INSTANCE_NEXT = INSTANCE.next()
|
||||
|
||||
@JvmField
|
||||
val INVALID_VERSION = JvmMetadataVersion()
|
||||
}
|
||||
|
||||
+3
-2
@@ -53,6 +53,7 @@ class ModuleMapping private constructor(
|
||||
debugName: String,
|
||||
skipMetadataVersionCheck: Boolean,
|
||||
isJvmPackageNameSupported: Boolean,
|
||||
metadataVersionFromLanguageVersion: JvmMetadataVersion,
|
||||
reportIncompatibleVersionError: (JvmMetadataVersion) -> Unit,
|
||||
): ModuleMapping {
|
||||
if (bytes == null) {
|
||||
@@ -63,7 +64,7 @@ class ModuleMapping private constructor(
|
||||
|
||||
val versionNumber = readVersionNumber(stream) ?: return CORRUPTED
|
||||
val preVersion = JvmMetadataVersion(*versionNumber)
|
||||
if (!skipMetadataVersionCheck && !preVersion.isCompatible()) {
|
||||
if (!skipMetadataVersionCheck && !preVersion.isCompatible(metadataVersionFromLanguageVersion)) {
|
||||
reportIncompatibleVersionError(preVersion)
|
||||
return EMPTY
|
||||
}
|
||||
@@ -72,7 +73,7 @@ class ModuleMapping private constructor(
|
||||
val flags = if (isKotlin1Dot4OrLater(preVersion)) stream.readInt() else 0
|
||||
|
||||
val version = JvmMetadataVersion(versionNumber, (flags and STRICT_METADATA_VERSION_SEMANTICS_FLAG) != 0)
|
||||
if (!skipMetadataVersionCheck && !version.isCompatible()) {
|
||||
if (!skipMetadataVersionCheck && !version.isCompatible(metadataVersionFromLanguageVersion)) {
|
||||
reportIncompatibleVersionError(version)
|
||||
return EMPTY
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user