Refactor boolean IR ABI stability flag to enum

Introduce an enum DeserializedContainerAbiStability with two values.
This is needed in order to support another reason for ABI instability in
a subsequent commit, namely "unstable because compiled by FIR".

 #KT-43592
This commit is contained in:
Alexander Udalov
2020-12-07 21:02:01 +01:00
parent b7d32a8754
commit cbd90c3af5
12 changed files with 50 additions and 18 deletions
@@ -298,7 +298,7 @@ class GenerationState private constructor(
?: if (languageVersionSettings.languageVersion >= LanguageVersion.LATEST_STABLE) JvmMetadataVersion.INSTANCE ?: if (languageVersionSettings.languageVersion >= LanguageVersion.LATEST_STABLE) JvmMetadataVersion.INSTANCE
else JvmMetadataVersion(1, 1, 18) else JvmMetadataVersion(1, 1, 18)
val isIrWithStableAbi = configuration.getBoolean(JVMConfigurationKeys.IS_IR_WITH_STABLE_ABI) val abiStability = configuration.get(JVMConfigurationKeys.ABI_STABILITY)
val globalSerializationBindings = JvmSerializationBindings() val globalSerializationBindings = JvmSerializationBindings()
var mapInlineClass: (ClassDescriptor) -> Type = { descriptor -> typeMapper.mapType(descriptor.defaultType) } var mapInlineClass: (ClassDescriptor) -> Type = { descriptor -> typeMapper.mapType(descriptor.defaultType) }
@@ -172,7 +172,9 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr
put(JVMConfigurationKeys.PARAMETERS_METADATA, arguments.javaParameters) put(JVMConfigurationKeys.PARAMETERS_METADATA, arguments.javaParameters)
put(JVMConfigurationKeys.IR, arguments.useIR && !arguments.noUseIR) put(JVMConfigurationKeys.IR, arguments.useIR && !arguments.noUseIR)
put(JVMConfigurationKeys.IS_IR_WITH_STABLE_ABI, arguments.isIrWithStableAbi)
put(JVMConfigurationKeys.ABI_STABILITY, if (arguments.isIrWithStableAbi) JvmAbiStability.STABLE else JvmAbiStability.UNSTABLE)
put(JVMConfigurationKeys.DO_NOT_CLEAR_BINDING_CONTEXT, arguments.doNotClearBindingContext) put(JVMConfigurationKeys.DO_NOT_CLEAR_BINDING_CONTEXT, arguments.doNotClearBindingContext)
put(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, arguments.noCallAssertions) put(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, arguments.noCallAssertions)
put(JVMConfigurationKeys.DISABLE_RECEIVER_ASSERTIONS, arguments.noReceiverAssertions) put(JVMConfigurationKeys.DISABLE_RECEIVER_ASSERTIONS, arguments.noReceiverAssertions)
@@ -117,8 +117,8 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<List<String>> KLIB_PATHS = public static final CompilerConfigurationKey<List<String>> KLIB_PATHS =
CompilerConfigurationKey.create("Paths to .klib libraries"); CompilerConfigurationKey.create("Paths to .klib libraries");
public static final CompilerConfigurationKey<Boolean> IS_IR_WITH_STABLE_ABI = public static final CompilerConfigurationKey<JvmAbiStability> ABI_STABILITY =
CompilerConfigurationKey.create("Is IR with stable ABI"); CompilerConfigurationKey.create("ABI stability of class files produced by the JVM IR backend");
public static final CompilerConfigurationKey<Boolean> DO_NOT_CLEAR_BINDING_CONTEXT = public static final CompilerConfigurationKey<Boolean> DO_NOT_CLEAR_BINDING_CONTEXT =
CompilerConfigurationKey.create("When using the IR backend, do not clear BindingContext between psi2ir and lowerings"); CompilerConfigurationKey.create("When using the IR backend, do not clear BindingContext between psi2ir and lowerings");
@@ -0,0 +1,12 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.config
enum class JvmAbiStability(val description: String) {
STABLE("stable"),
UNSTABLE("unstable"),
;
}
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
import org.jetbrains.kotlin.resolve.calls.checkers.isComputingDeferredType import org.jetbrains.kotlin.resolve.calls.checkers.isComputingDeferredType
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -58,7 +59,7 @@ object MissingDependencyClassChecker : CallChecker {
if (source.isPreReleaseInvisible) { if (source.isPreReleaseInvisible) {
return PRE_RELEASE_CLASS.on(reportOn, source.presentableString) return PRE_RELEASE_CLASS.on(reportOn, source.presentableString)
} }
if (source.isInvisibleIrDependency) { if (source.abiStability == DeserializedContainerAbiStability.IR_UNSTABLE) {
return IR_COMPILED_CLASS.on(reportOn, source.presentableString) return IR_COMPILED_CLASS.on(reportOn, source.presentableString)
} }
} }
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.jvm.lower.hasAssertionsDisabledField
import org.jetbrains.kotlin.codegen.DescriptorAsmUtil import org.jetbrains.kotlin.codegen.DescriptorAsmUtil
import org.jetbrains.kotlin.codegen.inline.* import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.writeKotlinMetadata import org.jetbrains.kotlin.codegen.writeKotlinMetadata
import org.jetbrains.kotlin.config.JvmAbiStability
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
@@ -197,7 +198,7 @@ class ClassCodegen private constructor(
private fun generateKotlinMetadataAnnotation() { private fun generateKotlinMetadataAnnotation() {
// TODO: if `-Xmultifile-parts-inherit` is enabled, write the corresponding flag for parts and facades to [Metadata.extraInt]. // TODO: if `-Xmultifile-parts-inherit` is enabled, write the corresponding flag for parts and facades to [Metadata.extraInt].
var extraFlags = JvmAnnotationNames.METADATA_JVM_IR_FLAG var extraFlags = JvmAnnotationNames.METADATA_JVM_IR_FLAG
if (state.isIrWithStableAbi) { if (state.abiStability != JvmAbiStability.UNSTABLE) {
extraFlags += JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG extraFlags += JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG
} }
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.jvm.lower.hasAssertionsDisabledField
import org.jetbrains.kotlin.codegen.DescriptorAsmUtil import org.jetbrains.kotlin.codegen.DescriptorAsmUtil
import org.jetbrains.kotlin.codegen.inline.* import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.writeKotlinMetadata import org.jetbrains.kotlin.codegen.writeKotlinMetadata
import org.jetbrains.kotlin.config.JvmAbiStability
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
@@ -197,7 +198,7 @@ class ClassCodegen private constructor(
private fun generateKotlinMetadataAnnotation() { private fun generateKotlinMetadataAnnotation() {
// TODO: if `-Xmultifile-parts-inherit` is enabled, write the corresponding flag for parts and facades to [Metadata.extraInt]. // TODO: if `-Xmultifile-parts-inherit` is enabled, write the corresponding flag for parts and facades to [Metadata.extraInt].
var extraFlags = JvmAnnotationNames.METADATA_JVM_IR_FLAG var extraFlags = JvmAnnotationNames.METADATA_JVM_IR_FLAG
if (state.isIrWithStableAbi) { if (state.abiStability != JvmAbiStability.UNSTABLE) {
extraFlags += JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG extraFlags += JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG
} }
@@ -17,9 +17,16 @@ interface DeserializedContainerSource : SourceElement {
// True iff this container was compiled by the new IR backend, this compiler is not using the IR backend right now, // 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. // and no additional flags to override this behavior were specified.
val isInvisibleIrDependency: Boolean val abiStability: DeserializedContainerAbiStability
// This string should only be used in error messages // This string should only be used in error messages
val presentableString: String val presentableString: String
} }
enum class DeserializedContainerAbiStability {
// Either the container is stable, or this compiler is configured to ignore ABI stability of dependencies.
STABLE,
// The container is unstable because it is compiled with unstable JVM IR backend, and this compiler is _not_ configured to ignore that.
IR_UNSTABLE,
}
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.deserialization.ClassData import org.jetbrains.kotlin.serialization.deserialization.ClassData
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
import javax.inject.Inject import javax.inject.Inject
@@ -53,7 +54,7 @@ class DeserializedDescriptorResolver {
JvmProtoBufUtil.readClassDataFrom(data, strings) JvmProtoBufUtil.readClassDataFrom(data, strings)
} ?: return null } ?: return null
val source = KotlinJvmBinarySourceElement( val source = KotlinJvmBinarySourceElement(
kotlinClass, kotlinClass.incompatibility, kotlinClass.isPreReleaseInvisible, kotlinClass.isInvisibleJvmIrDependency kotlinClass, kotlinClass.incompatibility, kotlinClass.isPreReleaseInvisible, kotlinClass.abiStability
) )
return ClassData(nameResolver, classProto, kotlinClass.classHeader.metadataVersion, source) return ClassData(nameResolver, classProto, kotlinClass.classHeader.metadataVersion, source)
} }
@@ -66,7 +67,7 @@ class DeserializedDescriptorResolver {
} ?: return null } ?: return null
val source = JvmPackagePartSource( val source = JvmPackagePartSource(
kotlinClass, packageProto, nameResolver, kotlinClass.incompatibility, kotlinClass.isPreReleaseInvisible, kotlinClass, packageProto, nameResolver, kotlinClass.incompatibility, kotlinClass.isPreReleaseInvisible,
kotlinClass.isInvisibleJvmIrDependency kotlinClass.abiStability
) )
return DeserializedPackageMemberScope( return DeserializedPackageMemberScope(
descriptor, packageProto, nameResolver, kotlinClass.classHeader.metadataVersion, source, components descriptor, packageProto, nameResolver, kotlinClass.classHeader.metadataVersion, source, components
@@ -97,8 +98,12 @@ class DeserializedDescriptorResolver {
get() = !components.configuration.skipPrereleaseCheck && get() = !components.configuration.skipPrereleaseCheck &&
classHeader.isPreRelease && classHeader.metadataVersion == KOTLIN_1_3_M1_METADATA_VERSION classHeader.isPreRelease && classHeader.metadataVersion == KOTLIN_1_3_M1_METADATA_VERSION
private val KotlinJvmBinaryClass.isInvisibleJvmIrDependency: Boolean private val KotlinJvmBinaryClass.abiStability: DeserializedContainerAbiStability
get() = !components.configuration.allowUnstableDependencies && classHeader.isUnstableJvmIrBinary get() = when {
components.configuration.allowUnstableDependencies -> DeserializedContainerAbiStability.STABLE
classHeader.isUnstableJvmIrBinary -> DeserializedContainerAbiStability.IR_UNSTABLE
else -> DeserializedContainerAbiStability.STABLE
}
private fun readData(kotlinClass: KotlinJvmBinaryClass, expectedKinds: Set<KotlinClassHeader.Kind>): Array<String>? { private fun readData(kotlinClass: KotlinJvmBinaryClass, expectedKinds: Set<KotlinClassHeader.Kind>): Array<String>? {
val header = kotlinClass.classHeader val header = kotlinClass.classHeader
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
class JvmPackagePartSource( class JvmPackagePartSource(
@@ -25,7 +26,7 @@ class JvmPackagePartSource(
nameResolver: NameResolver, nameResolver: NameResolver,
override val incompatibility: IncompatibleVersionErrorData<JvmMetadataVersion>? = null, override val incompatibility: IncompatibleVersionErrorData<JvmMetadataVersion>? = null,
override val isPreReleaseInvisible: Boolean = false, override val isPreReleaseInvisible: Boolean = false,
override val isInvisibleIrDependency: Boolean = false, override val abiStability: DeserializedContainerAbiStability = DeserializedContainerAbiStability.STABLE,
val knownJvmBinaryClass: KotlinJvmBinaryClass? = null val knownJvmBinaryClass: KotlinJvmBinaryClass? = null
) : DeserializedContainerSource { ) : DeserializedContainerSource {
constructor( constructor(
@@ -34,7 +35,7 @@ class JvmPackagePartSource(
nameResolver: NameResolver, nameResolver: NameResolver,
incompatibility: IncompatibleVersionErrorData<JvmMetadataVersion>? = null, incompatibility: IncompatibleVersionErrorData<JvmMetadataVersion>? = null,
isPreReleaseInvisible: Boolean = false, isPreReleaseInvisible: Boolean = false,
isInvisibleIrDependency: Boolean = false abiStability: DeserializedContainerAbiStability = DeserializedContainerAbiStability.STABLE,
) : this( ) : this(
JvmClassName.byClassId(kotlinClass.classId), JvmClassName.byClassId(kotlinClass.classId),
kotlinClass.classHeader.multifileClassName?.let { kotlinClass.classHeader.multifileClassName?.let {
@@ -44,7 +45,7 @@ class JvmPackagePartSource(
nameResolver, nameResolver,
incompatibility, incompatibility,
isPreReleaseInvisible, isPreReleaseInvisible,
isInvisibleIrDependency, abiStability,
kotlinClass kotlinClass
) )
@@ -19,13 +19,14 @@ package org.jetbrains.kotlin.load.kotlin
import org.jetbrains.kotlin.descriptors.SourceFile import org.jetbrains.kotlin.descriptors.SourceFile
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
class KotlinJvmBinarySourceElement( class KotlinJvmBinarySourceElement(
val binaryClass: KotlinJvmBinaryClass, val binaryClass: KotlinJvmBinaryClass,
override val incompatibility: IncompatibleVersionErrorData<JvmMetadataVersion>? = null, override val incompatibility: IncompatibleVersionErrorData<JvmMetadataVersion>? = null,
override val isPreReleaseInvisible: Boolean = false, override val isPreReleaseInvisible: Boolean = false,
override val isInvisibleIrDependency: Boolean = false override val abiStability: DeserializedContainerAbiStability = DeserializedContainerAbiStability.STABLE,
) : DeserializedContainerSource { ) : DeserializedContainerSource {
override val presentableString: String override val presentableString: String
get() = "Class '${binaryClass.classId.asSingleFqName().asString()}'" get() = "Class '${binaryClass.classId.asSingleFqName().asString()}'"
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.serialization.deserialization.* import org.jetbrains.kotlin.serialization.deserialization.*
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue import org.jetbrains.kotlin.storage.getValue
@@ -94,8 +95,8 @@ class KotlinJavascriptPackageFragment(
override val isPreReleaseInvisible: Boolean = override val isPreReleaseInvisible: Boolean =
configuration.reportErrorsOnPreReleaseDependencies && (header.flags and 1) != 0 configuration.reportErrorsOnPreReleaseDependencies && (header.flags and 1) != 0
override val isInvisibleIrDependency: Boolean override val abiStability: DeserializedContainerAbiStability
get() = false get() = DeserializedContainerAbiStability.STABLE
override val presentableString: String override val presentableString: String
get() = "Package '$fqName'" get() = "Package '$fqName'"