diff --git a/build-common/src/org/jetbrains/kotlin/incremental/JavaClassesSerializerExtension.kt b/build-common/src/org/jetbrains/kotlin/incremental/JavaClassesSerializerExtension.kt index bbea5202cf4..ae6c45ab404 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/JavaClassesSerializerExtension.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/JavaClassesSerializerExtension.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.java.JavaClassProtoBuf +import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.serialization.DescriptorSerializer @@ -28,8 +29,12 @@ import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerial // It uses BuiltInSerializerProtocol for annotations serialization class JavaClassesSerializerExtension : KotlinSerializerExtensionBase(BuiltInSerializerProtocol) { - override fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder) { - super.serializeClass(descriptor, proto) + override fun serializeClass( + descriptor: ClassDescriptor, + proto: ProtoBuf.Class.Builder, + versionRequirementTable: MutableVersionRequirementTable + ) { + super.serializeClass(descriptor, proto, versionRequirementTable) if (descriptor.visibility == JavaVisibilities.PACKAGE_VISIBILITY) { proto.setExtension(JavaClassProtoBuf.isPackagePrivateClass, true) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt index 59dcecfbd6f..a86455ac5a5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt @@ -19,12 +19,16 @@ import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf import org.jetbrains.kotlin.metadata.jvm.deserialization.ClassMapperLite import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil +import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.protobuf.GeneratedMessageLite import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface +import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.nonSourceAnnotations import org.jetbrains.kotlin.serialization.DescriptorSerializer +import org.jetbrains.kotlin.serialization.DescriptorSerializer.Companion.writeVersionRequirement import org.jetbrains.kotlin.serialization.SerializerExtension import org.jetbrains.kotlin.types.FlexibleType import org.jetbrains.kotlin.types.KotlinType @@ -45,7 +49,11 @@ class JvmSerializerExtension(private val bindings: JvmSerializationBindings, sta return useTypeTable } - override fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder) { + override fun serializeClass( + descriptor: ClassDescriptor, + proto: ProtoBuf.Class.Builder, + versionRequirementTable: MutableVersionRequirementTable + ) { if (moduleName != JvmAbi.DEFAULT_MODULE_NAME) { proto.setExtension(JvmProtoBuf.classModuleName, stringTable.getStringIndex(moduleName)) } @@ -53,6 +61,26 @@ class JvmSerializerExtension(private val bindings: JvmSerializationBindings, sta val containerAsmType = if (DescriptorUtils.isInterface(descriptor)) typeMapper.mapDefaultImpls(descriptor) else typeMapper.mapClass(descriptor) writeLocalProperties(proto, containerAsmType, JvmProtoBuf.classLocalVariable) + writeVersionRequirementForJvmDefaultIfNeeded(descriptor, proto, versionRequirementTable) + } + + // Interfaces which have @JvmDefault members somewhere in the hierarchy need the compiler 1.2.40+ + // so that the generated bridges in subclasses would call the super members correctly + private fun writeVersionRequirementForJvmDefaultIfNeeded( + classDescriptor: ClassDescriptor, + builder: ProtoBuf.Class.Builder, + versionRequirementTable: MutableVersionRequirementTable + ) { + if ( + isInterface(classDescriptor) && + classDescriptor.unsubstitutedMemberScope.getContributedDescriptors().any { + it is CallableMemberDescriptor && it.hasJvmDefaultAnnotation() + } + ) { + assert(!builder.hasVersionRequirement()) { "VersionRequirement should be empty for $classDescriptor" } + builder.versionRequirement = + writeVersionRequirement(1, 2, 40, ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION, versionRequirementTable) + } } override fun serializePackage(packageFqName: FqName, proto: ProtoBuf.Package.Builder) { diff --git a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt index 53c728442ce..b2788ebba55 100644 --- a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt +++ b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt @@ -20,8 +20,7 @@ import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTabl import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry -import org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface +import org.jetbrains.kotlin.resolve.DescriptorUtils.* import org.jetbrains.kotlin.resolve.MemberComparator import org.jetbrains.kotlin.resolve.RequireKotlinNames import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation @@ -144,16 +143,14 @@ class DescriptorSerializer private constructor( val requirement = serializeVersionRequirement(classDescriptor) if (requirement != null) { builder.versionRequirement = requirement - } else { - writeVersionRequirementForJvmDefaultIfNeeded(classDescriptor, builder) } + extension.serializeClass(classDescriptor, builder, versionRequirementTable) + val versionRequirementTableProto = versionRequirementTable.serialize() if (versionRequirementTableProto != null) { builder.versionRequirementTable = versionRequirementTableProto } - - extension.serializeClass(classDescriptor, builder) return builder } @@ -622,19 +619,6 @@ class DescriptorSerializer private constructor( return builder } - // Interfaces which have @JvmDefault members somewhere in the hierarchy need the compiler 1.2.40+ - // so that the generated bridges in subclasses would call the super members correctly - private fun writeVersionRequirementForJvmDefaultIfNeeded(classDescriptor: ClassDescriptor, builder: ProtoBuf.Class.Builder) { - if ( - isInterface(classDescriptor) && - classDescriptor.unsubstitutedMemberScope.getContributedDescriptors().any { - it is CallableMemberDescriptor && it.hasJvmDefaultAnnotation() - } - ) { - builder.versionRequirement = writeVersionRequirement(1, 2, 40, ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION) - } - } - private fun writeVersionRequirement(languageFeature: LanguageFeature): Int { val languageVersion = languageFeature.sinceVersion!! return writeVersionRequirement( @@ -644,16 +628,7 @@ class DescriptorSerializer private constructor( } private fun writeVersionRequirement(major: Int, minor: Int, patch: Int, versionKind: ProtoBuf.VersionRequirement.VersionKind): Int { - val requirement = ProtoBuf.VersionRequirement.newBuilder().apply { - VersionRequirement.Version(major, minor, patch).encode( - writeVersion = { version = it }, - writeVersionFull = { versionFull = it } - ) - if (versionKind != defaultInstanceForType.versionKind) { - this.versionKind = versionKind - } - } - return versionRequirementTable[requirement] + return writeVersionRequirement(major, minor, patch, versionKind, versionRequirementTable) } // Returns index into versionRequirementTable, or null if there's no @RequireKotlin on the descriptor @@ -782,5 +757,24 @@ class DescriptorSerializer private constructor( //NOTE: the exact comparator does matter here Collections.sort(this, MemberComparator.INSTANCE) } + + fun writeVersionRequirement( + major: Int, + minor: Int, + patch: Int, + versionKind: ProtoBuf.VersionRequirement.VersionKind, + versionRequirementTable: MutableVersionRequirementTable + ): Int { + val requirement = ProtoBuf.VersionRequirement.newBuilder().apply { + VersionRequirement.Version(major, minor, patch).encode( + writeVersion = { version = it }, + writeVersionFull = { versionFull = it } + ) + if (versionKind != defaultInstanceForType.versionKind) { + this.versionKind = versionKind + } + } + return versionRequirementTable[requirement] + } } } diff --git a/compiler/serialization/src/org/jetbrains/kotlin/serialization/SerializerExtension.kt b/compiler/serialization/src/org/jetbrains/kotlin/serialization/SerializerExtension.kt index 7cc1d2153cd..7efa696ad7f 100644 --- a/compiler/serialization/src/org/jetbrains/kotlin/serialization/SerializerExtension.kt +++ b/compiler/serialization/src/org/jetbrains/kotlin/serialization/SerializerExtension.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.serialization import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.metadata.ProtoBuf +import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.types.FlexibleType import org.jetbrains.kotlin.types.KotlinType @@ -27,7 +28,11 @@ abstract class SerializerExtension { get() = null - open fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder) { + open fun serializeClass( + descriptor: ClassDescriptor, + proto: ProtoBuf.Class.Builder, + versionRequirementTable: MutableVersionRequirementTable + ) { } open fun serializePackage(packageFqName: FqName, proto: ProtoBuf.Package.Builder) { diff --git a/compiler/serialization/src/org/jetbrains/kotlin/serialization/SerializerExtensionBase.kt b/compiler/serialization/src/org/jetbrains/kotlin/serialization/SerializerExtensionBase.kt index ac85508fe3d..c9bf9c3e823 100644 --- a/compiler/serialization/src/org/jetbrains/kotlin/serialization/SerializerExtensionBase.kt +++ b/compiler/serialization/src/org/jetbrains/kotlin/serialization/SerializerExtensionBase.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.serialization import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.metadata.ProtoBuf +import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.constants.NullValue import org.jetbrains.kotlin.resolve.descriptorUtil.nonSourceAnnotations @@ -26,7 +27,11 @@ import org.jetbrains.kotlin.types.KotlinType open class KotlinSerializerExtensionBase(private val protocol: SerializerExtensionProtocol) : SerializerExtension() { override val stringTable = StringTableImpl() - override fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder) { + override fun serializeClass( + descriptor: ClassDescriptor, + proto: ProtoBuf.Class.Builder, + versionRequirementTable: MutableVersionRequirementTable + ) { for (annotation in descriptor.nonSourceAnnotations) { proto.addExtension(protocol.classAnnotation, annotationSerializer.serializeAnnotation(annotation)) } diff --git a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializerExtension.kt b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializerExtension.kt index 92a1d1922f1..ac1251e584f 100644 --- a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializerExtension.kt +++ b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializerExtension.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.js.JsProtoBuf +import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite @@ -41,12 +42,16 @@ class KotlinJavascriptSerializerExtension( lowerProto.flexibleTypeCapabilitiesId = stringTable.getStringIndex(DynamicTypeDeserializer.id) } - override fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder) { + override fun serializeClass( + descriptor: ClassDescriptor, + proto: ProtoBuf.Class.Builder, + versionRequirementTable: MutableVersionRequirementTable + ) { val id = getFileId(descriptor) if (id != null) { proto.setExtension(JsProtoBuf.classContainingFileId, id) } - super.serializeClass(descriptor, proto) + super.serializeClass(descriptor, proto, versionRequirementTable) } override fun serializeProperty(descriptor: PropertyDescriptor, proto: ProtoBuf.Property.Builder) {