Add new compiler errors and flags when JVM compiles against JVM IR
From now on, the old JVM backend will report an error by default when compiling against class files produced by the JVM IR backend. This is needed because we're not yet sure that the ABI generated by JVM IR is fully correct and do not want to land in a 2-dimensional compatibility situation where we'll need to consider twice more scenarios when introducing any breaking change in the language. This is generally OK since the JVM IR backend is still going to be experimental in 1.4. However, for purposes of users which _do_ need to compile something with the old backend against JVM IR, we provide two new compiler flags: * -Xallow-jvm-ir-dependencies -- allows to suppress the error when compiling with the old backend against JVM IR. * -Xir-binary-with-stable-api -- allows to mark the generated binaries as stable, when compiling anything with JVM IR, so that dependent modules will compile even with the old backend automatically. In this case, the author usually does not care for the generated ABI, or s/he ensures that it's consistent with the one expected by the old compiler with some external tools. Internally, this is implemented by storing two new flags in kotlin.Metadata: one tells if the class file was compiled with the JVM IR, and another tells if the class file is stable (in case it's compiled with JVM IR). Implementation is similar to the diagnostic reported by the pre-release dependency checker.
This commit is contained in:
@@ -39,6 +39,8 @@ public final class JvmAnnotationNames {
|
||||
public static final int METADATA_PRE_RELEASE_FLAG = 1 << 1;
|
||||
public static final int METADATA_SCRIPT_FLAG = 1 << 2;
|
||||
public static final int METADATA_STRICT_VERSION_SEMANTICS_FLAG = 1 << 3;
|
||||
public static final int METADATA_JVM_IR_FLAG = 1 << 4;
|
||||
public static final int METADATA_JVM_IR_STABLE_ABI_FLAG = 1 << 5;
|
||||
|
||||
public static final Name DEFAULT_ANNOTATION_MEMBER_NAME = Name.identifier("value");
|
||||
|
||||
|
||||
+8
-2
@@ -52,7 +52,9 @@ class DeserializedDescriptorResolver {
|
||||
val (nameResolver, classProto) = parseProto(kotlinClass) {
|
||||
JvmProtoBufUtil.readClassDataFrom(data, strings)
|
||||
} ?: return null
|
||||
val source = KotlinJvmBinarySourceElement(kotlinClass, kotlinClass.incompatibility, kotlinClass.isPreReleaseInvisible)
|
||||
val source = KotlinJvmBinarySourceElement(
|
||||
kotlinClass, kotlinClass.incompatibility, kotlinClass.isPreReleaseInvisible, kotlinClass.isInvisibleJvmIrDependency
|
||||
)
|
||||
return ClassData(nameResolver, classProto, kotlinClass.classHeader.metadataVersion, source)
|
||||
}
|
||||
|
||||
@@ -63,7 +65,8 @@ class DeserializedDescriptorResolver {
|
||||
JvmProtoBufUtil.readPackageDataFrom(data, strings)
|
||||
} ?: return null
|
||||
val source = JvmPackagePartSource(
|
||||
kotlinClass, packageProto, nameResolver, kotlinClass.incompatibility, kotlinClass.isPreReleaseInvisible
|
||||
kotlinClass, packageProto, nameResolver, kotlinClass.incompatibility, kotlinClass.isPreReleaseInvisible,
|
||||
kotlinClass.isInvisibleJvmIrDependency
|
||||
)
|
||||
return DeserializedPackageMemberScope(
|
||||
descriptor, packageProto, nameResolver, kotlinClass.classHeader.metadataVersion, source, components
|
||||
@@ -94,6 +97,9 @@ class DeserializedDescriptorResolver {
|
||||
get() = !components.configuration.skipMetadataVersionCheck &&
|
||||
classHeader.isPreRelease && classHeader.metadataVersion == KOTLIN_1_3_M1_METADATA_VERSION
|
||||
|
||||
private val KotlinJvmBinaryClass.isInvisibleJvmIrDependency: Boolean
|
||||
get() = components.configuration.reportErrorsOnIrDependencies && classHeader.isUnstableJvmIrBinary
|
||||
|
||||
private fun readData(kotlinClass: KotlinJvmBinaryClass, expectedKinds: Set<KotlinClassHeader.Kind>): Array<String>? {
|
||||
val header = kotlinClass.classHeader
|
||||
return (header.data ?: header.incompatibleData)?.takeIf { header.kind in expectedKinds }
|
||||
|
||||
@@ -36,6 +36,7 @@ class JvmPackagePartSource(
|
||||
nameResolver: NameResolver,
|
||||
override val incompatibility: IncompatibleVersionErrorData<JvmMetadataVersion>? = null,
|
||||
override val isPreReleaseInvisible: Boolean = false,
|
||||
override val isInvisibleIrDependency: Boolean = false,
|
||||
val knownJvmBinaryClass: KotlinJvmBinaryClass? = null
|
||||
) : DeserializedContainerSource {
|
||||
constructor(
|
||||
@@ -43,7 +44,8 @@ class JvmPackagePartSource(
|
||||
packageProto: ProtoBuf.Package,
|
||||
nameResolver: NameResolver,
|
||||
incompatibility: IncompatibleVersionErrorData<JvmMetadataVersion>? = null,
|
||||
isPreReleaseInvisible: Boolean = false
|
||||
isPreReleaseInvisible: Boolean = false,
|
||||
isInvisibleIrDependency: Boolean = false
|
||||
) : this(
|
||||
JvmClassName.byClassId(kotlinClass.classId),
|
||||
kotlinClass.classHeader.multifileClassName?.let {
|
||||
@@ -53,6 +55,7 @@ class JvmPackagePartSource(
|
||||
nameResolver,
|
||||
incompatibility,
|
||||
isPreReleaseInvisible,
|
||||
isInvisibleIrDependency,
|
||||
kotlinClass
|
||||
)
|
||||
|
||||
|
||||
+2
-1
@@ -24,7 +24,8 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
|
||||
class KotlinJvmBinarySourceElement(
|
||||
val binaryClass: KotlinJvmBinaryClass,
|
||||
override val incompatibility: IncompatibleVersionErrorData<JvmMetadataVersion>? = null,
|
||||
override val isPreReleaseInvisible: Boolean = false
|
||||
override val isPreReleaseInvisible: Boolean = false,
|
||||
override val isInvisibleIrDependency: Boolean = false
|
||||
) : DeserializedContainerSource {
|
||||
override val presentableString: String
|
||||
get() = "Class '${binaryClass.classId.asSingleFqName().asString()}'"
|
||||
|
||||
@@ -71,6 +71,10 @@ class KotlinClassHeader(
|
||||
DELEGATING
|
||||
} else null
|
||||
|
||||
val isUnstableJvmIrBinary: Boolean
|
||||
get() = (extraInt and JvmAnnotationNames.METADATA_JVM_IR_FLAG) != 0 &&
|
||||
(extraInt and JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG == 0)
|
||||
|
||||
val isPreRelease: Boolean
|
||||
get() = (extraInt and JvmAnnotationNames.METADATA_PRE_RELEASE_FLAG) != 0
|
||||
|
||||
|
||||
+3
@@ -12,6 +12,9 @@ interface DeserializationConfiguration {
|
||||
val reportErrorsOnPreReleaseDependencies: Boolean
|
||||
get() = false
|
||||
|
||||
val reportErrorsOnIrDependencies: Boolean
|
||||
get() = false
|
||||
|
||||
val typeAliasesAllowed: Boolean
|
||||
get() = true
|
||||
|
||||
|
||||
+4
@@ -52,6 +52,10 @@ interface DeserializedContainerSource : SourceElement {
|
||||
// True iff this is container is "invisible" because it's loaded from a pre-release class and this compiler is a release
|
||||
val isPreReleaseInvisible: Boolean
|
||||
|
||||
// True iff this container was compiled by the new IR backend, this compiler is not using the IR backend right now,
|
||||
// and no additional flags to override this behavior were specified.
|
||||
val isInvisibleIrDependency: Boolean
|
||||
|
||||
// This string should only be used in error messages
|
||||
val presentableString: String
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user