Enhance API/messages around BinaryVersion / JvmMetadataVersion

This commit is contained in:
Mikhail Glukhikh
2023-01-04 11:38:28 +01:00
parent 13502abab9
commit cbedbda527
13 changed files with 71 additions and 59 deletions
@@ -9,6 +9,8 @@ import org.jetbrains.kotlin.name.ClassId
data class IncompatibleVersionErrorData<out T>(
val actualVersion: T,
val compilerVersion: T,
val languageVersion: T,
val expectedVersion: T,
val filePath: String,
val classId: ClassId
@@ -85,7 +85,12 @@ class DeserializedDescriptorResolver {
get() {
if (skipMetadataVersionCheck || classHeader.metadataVersion.isCompatible(ownMetadataVersion)) return null
return IncompatibleVersionErrorData(
classHeader.metadataVersion, maxOf(ownMetadataVersion.prev(), JvmMetadataVersion.INSTANCE), location, classId
actualVersion = classHeader.metadataVersion,
compilerVersion = JvmMetadataVersion.INSTANCE,
languageVersion = ownMetadataVersion,
expectedVersion = ownMetadataVersion.lastSupportedVersionWithThisLanguageVersion(classHeader.metadataVersion.isStrictSemantics),
filePath = location,
classId = classId
)
}
@@ -14,6 +14,13 @@ import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
class JvmMetadataVersion(versionArray: IntArray, val isStrictSemantics: Boolean) : BinaryVersion(*versionArray) {
constructor(vararg numbers: Int) : this(numbers, isStrictSemantics = false)
fun lastSupportedVersionWithThisLanguageVersion(isStrictSemantics: Boolean): JvmMetadataVersion {
// * 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
return if (forwardCompatibility.newerThan(this)) forwardCompatibility else this
}
override fun isCompatibleWithCurrentCompilerVersion(): Boolean {
return isCompatibleInternal(INSTANCE_NEXT)
}
@@ -21,10 +28,7 @@ class JvmMetadataVersion(versionArray: IntArray, val isStrictSemantics: Boolean)
fun isCompatible(metadataVersionFromLanguageVersion: JvmMetadataVersion): Boolean {
// Special case for bootstrap: 1.8 can read 2.0
if (major == 2 && minor == 0 && INSTANCE.major == 1 && INSTANCE.minor == 8) return true
// * 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)
val limitVersion = metadataVersionFromLanguageVersion.lastSupportedVersionWithThisLanguageVersion(isStrictSemantics)
return isCompatibleInternal(limitVersion)
}
@@ -34,24 +38,28 @@ class JvmMetadataVersion(versionArray: IntArray, val isStrictSemantics: Boolean)
// The same for 0.*
if (major == 0) return false
// Otherwise we just compare with the given limitVersion
return this <= limitVersion
return !newerThan(limitVersion)
}
fun next(): JvmMetadataVersion {
if (minor < 9 || major > 1) return JvmMetadataVersion(major, minor + 1, 0)
return JvmMetadataVersion(2, 0, 0)
}
fun next(): JvmMetadataVersion =
if (major == 1 && minor == 9) JvmMetadataVersion(2, 0, 0)
else JvmMetadataVersion(major, minor + 1, 0)
fun prev(): JvmMetadataVersion {
if (minor > 0) return JvmMetadataVersion(major, minor - 1, 0)
return JvmMetadataVersion(major - 1, 9, 0)
private fun newerThan(other: JvmMetadataVersion): Boolean {
return when {
major > other.major -> true
major < other.major -> false
minor > other.minor -> true
else -> false
}
}
companion object {
@JvmField
val INSTANCE = JvmMetadataVersion(1, 8, 0)
private val INSTANCE_NEXT = INSTANCE.next()
@JvmField
val INSTANCE_NEXT = INSTANCE.next()
@JvmField
val INVALID_VERSION = JvmMetadataVersion()
@@ -14,7 +14,7 @@ package org.jetbrains.kotlin.metadata.deserialization
* - Patch version can be increased freely and is only supposed to be used for debugging. Increase the patch version when you
* make a change to binaries which is both forward- and backward compatible.
*/
abstract class BinaryVersion(private vararg val numbers: Int) : Comparable<BinaryVersion> {
abstract class BinaryVersion(private vararg val numbers: Int) {
val major: Int = numbers.getOrNull(0) ?: UNKNOWN
val minor: Int = numbers.getOrNull(1) ?: UNKNOWN
val patch: Int = numbers.getOrNull(2) ?: UNKNOWN
@@ -87,18 +87,6 @@ abstract class BinaryVersion(private vararg val numbers: Int) : Comparable<Binar
return result
}
override fun compareTo(other: BinaryVersion): Int {
return when {
major > other.major -> 1
major < other.major -> -1
minor > other.minor -> 1
minor < other.minor -> -1
patch > other.patch -> 1
patch < other.patch -> -1
else -> 0
}
}
companion object {
const val MAX_LENGTH = 1024
private const val UNKNOWN = -1