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
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()
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.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.DISABLE_CALL_ASSERTIONS, arguments.noCallAssertions)
put(JVMConfigurationKeys.DISABLE_RECEIVER_ASSERTIONS, arguments.noReceiverAssertions)
@@ -117,8 +117,8 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<List<String>> KLIB_PATHS =
CompilerConfigurationKey.create("Paths to .klib libraries");
public static final CompilerConfigurationKey<Boolean> IS_IR_WITH_STABLE_ABI =
CompilerConfigurationKey.create("Is IR with stable ABI");
public static final CompilerConfigurationKey<JvmAbiStability> ABI_STABILITY =
CompilerConfigurationKey.create("ABI stability of class files produced by the JVM IR backend");
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");
@@ -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.model.ResolvedCall
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.DeserializedMemberDescriptor
import org.jetbrains.kotlin.types.KotlinType
@@ -58,7 +59,7 @@ object MissingDependencyClassChecker : CallChecker {
if (source.isPreReleaseInvisible) {
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)
}
}
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.jvm.lower.hasAssertionsDisabledField
import org.jetbrains.kotlin.codegen.DescriptorAsmUtil
import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.writeKotlinMetadata
import org.jetbrains.kotlin.config.JvmAbiStability
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
@@ -197,7 +198,7 @@ class ClassCodegen private constructor(
private fun generateKotlinMetadataAnnotation() {
// 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
if (state.isIrWithStableAbi) {
if (state.abiStability != JvmAbiStability.UNSTABLE) {
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.inline.*
import org.jetbrains.kotlin.codegen.writeKotlinMetadata
import org.jetbrains.kotlin.config.JvmAbiStability
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
@@ -197,7 +198,7 @@ class ClassCodegen private constructor(
private fun generateKotlinMetadataAnnotation() {
// 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
if (state.isIrWithStableAbi) {
if (state.abiStability != JvmAbiStability.UNSTABLE) {
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,
// 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
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.DeserializationComponents
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
import javax.inject.Inject
@@ -53,7 +54,7 @@ class DeserializedDescriptorResolver {
JvmProtoBufUtil.readClassDataFrom(data, strings)
} ?: return null
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)
}
@@ -66,7 +67,7 @@ class DeserializedDescriptorResolver {
} ?: return null
val source = JvmPackagePartSource(
kotlinClass, packageProto, nameResolver, kotlinClass.incompatibility, kotlinClass.isPreReleaseInvisible,
kotlinClass.isInvisibleJvmIrDependency
kotlinClass.abiStability
)
return DeserializedPackageMemberScope(
descriptor, packageProto, nameResolver, kotlinClass.classHeader.metadataVersion, source, components
@@ -97,8 +98,12 @@ class DeserializedDescriptorResolver {
get() = !components.configuration.skipPrereleaseCheck &&
classHeader.isPreRelease && classHeader.metadataVersion == KOTLIN_1_3_M1_METADATA_VERSION
private val KotlinJvmBinaryClass.isInvisibleJvmIrDependency: Boolean
get() = !components.configuration.allowUnstableDependencies && classHeader.isUnstableJvmIrBinary
private val KotlinJvmBinaryClass.abiStability: DeserializedContainerAbiStability
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>? {
val header = kotlinClass.classHeader
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
class JvmPackagePartSource(
@@ -25,7 +26,7 @@ class JvmPackagePartSource(
nameResolver: NameResolver,
override val incompatibility: IncompatibleVersionErrorData<JvmMetadataVersion>? = null,
override val isPreReleaseInvisible: Boolean = false,
override val isInvisibleIrDependency: Boolean = false,
override val abiStability: DeserializedContainerAbiStability = DeserializedContainerAbiStability.STABLE,
val knownJvmBinaryClass: KotlinJvmBinaryClass? = null
) : DeserializedContainerSource {
constructor(
@@ -34,7 +35,7 @@ class JvmPackagePartSource(
nameResolver: NameResolver,
incompatibility: IncompatibleVersionErrorData<JvmMetadataVersion>? = null,
isPreReleaseInvisible: Boolean = false,
isInvisibleIrDependency: Boolean = false
abiStability: DeserializedContainerAbiStability = DeserializedContainerAbiStability.STABLE,
) : this(
JvmClassName.byClassId(kotlinClass.classId),
kotlinClass.classHeader.multifileClassName?.let {
@@ -44,7 +45,7 @@ class JvmPackagePartSource(
nameResolver,
incompatibility,
isPreReleaseInvisible,
isInvisibleIrDependency,
abiStability,
kotlinClass
)
@@ -19,13 +19,14 @@ package org.jetbrains.kotlin.load.kotlin
import org.jetbrains.kotlin.descriptors.SourceFile
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
class KotlinJvmBinarySourceElement(
val binaryClass: KotlinJvmBinaryClass,
override val incompatibility: IncompatibleVersionErrorData<JvmMetadataVersion>? = null,
override val isPreReleaseInvisible: Boolean = false,
override val isInvisibleIrDependency: Boolean = false
override val abiStability: DeserializedContainerAbiStability = DeserializedContainerAbiStability.STABLE,
) : DeserializedContainerSource {
override val presentableString: String
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.resolve.DescriptorUtils
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.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue
@@ -94,8 +95,8 @@ class KotlinJavascriptPackageFragment(
override val isPreReleaseInvisible: Boolean =
configuration.reportErrorsOnPreReleaseDependencies && (header.flags and 1) != 0
override val isInvisibleIrDependency: Boolean
get() = false
override val abiStability: DeserializedContainerAbiStability
get() = DeserializedContainerAbiStability.STABLE
override val presentableString: String
get() = "Package '$fqName'"