From cbd90c3af5b7b8ae935c50ddc040ccf6624ade09 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 7 Dec 2020 21:02:01 +0100 Subject: [PATCH] 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 --- .../kotlin/codegen/state/GenerationState.kt | 2 +- .../org/jetbrains/kotlin/cli/jvm/jvmArguments.kt | 4 +++- .../kotlin/config/JVMConfigurationKeys.java | 4 ++-- .../org/jetbrains/kotlin/config/JvmAbiStability.kt | 12 ++++++++++++ .../checkers/MissingDependencyClassChecker.kt | 3 ++- .../kotlin/backend/jvm/codegen/ClassCodegen.kt | 3 ++- .../kotlin/backend/jvm/codegen/ClassCodegen.kt.201 | 3 ++- .../descriptors/DeserializedContainerSource.kt | 9 ++++++++- .../load/kotlin/DeserializedDescriptorResolver.kt | 13 +++++++++---- .../kotlin/load/kotlin/JvmPackagePartSource.kt | 7 ++++--- .../load/kotlin/KotlinJvmBinarySourceElement.kt | 3 ++- .../js/KotlinJavascriptPackageFragment.kt | 5 +++-- 12 files changed, 50 insertions(+), 18 deletions(-) create mode 100644 compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmAbiStability.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt index 1923db861c7..844cfe00604 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt @@ -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) } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt index 709ba73a6b3..0df11b8c373 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt @@ -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) diff --git a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java index de4c0f9e015..41baa5d8707 100644 --- a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java +++ b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java @@ -117,8 +117,8 @@ public class JVMConfigurationKeys { public static final CompilerConfigurationKey> KLIB_PATHS = CompilerConfigurationKey.create("Paths to .klib libraries"); - public static final CompilerConfigurationKey IS_IR_WITH_STABLE_ABI = - CompilerConfigurationKey.create("Is IR with stable ABI"); + public static final CompilerConfigurationKey ABI_STABILITY = + CompilerConfigurationKey.create("ABI stability of class files produced by the JVM IR backend"); public static final CompilerConfigurationKey DO_NOT_CLEAR_BINDING_CONTEXT = CompilerConfigurationKey.create("When using the IR backend, do not clear BindingContext between psi2ir and lowerings"); diff --git a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmAbiStability.kt b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmAbiStability.kt new file mode 100644 index 00000000000..90fd1ca9d64 --- /dev/null +++ b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmAbiStability.kt @@ -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"), + ; +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencyClassChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencyClassChecker.kt index b1f6bcd4ef5..6bd2e0562be 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencyClassChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencyClassChecker.kt @@ -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) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index db877966a40..e5b0042e391 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -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 } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt.201 b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt.201 index 99b5bd200e4..70b0eb0d719 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt.201 +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt.201 @@ -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 } diff --git a/core/compiler.common/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedContainerSource.kt b/core/compiler.common/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedContainerSource.kt index 28748ed8c7e..f00c58b2d23 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedContainerSource.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedContainerSource.kt @@ -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, +} diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt index 24970d50c33..9a659433a4f 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt @@ -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): Array? { val header = kotlinClass.classHeader diff --git a/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/JvmPackagePartSource.kt b/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/JvmPackagePartSource.kt index fd24fcd2342..418779741af 100644 --- a/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/JvmPackagePartSource.kt +++ b/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/JvmPackagePartSource.kt @@ -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? = 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? = 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 ) diff --git a/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinarySourceElement.kt b/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinarySourceElement.kt index 9d088888b7a..27114c687b2 100644 --- a/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinarySourceElement.kt +++ b/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinarySourceElement.kt @@ -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? = 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()}'" diff --git a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptPackageFragment.kt b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptPackageFragment.kt index 484abea58c7..d2028c2f820 100644 --- a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptPackageFragment.kt +++ b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptPackageFragment.kt @@ -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'"