diff --git a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt index 96acc8e1dc2..42358f48bbb 100644 --- a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt +++ b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt @@ -33,9 +33,11 @@ import org.jetbrains.kotlin.resolve.constants.IntValue import org.jetbrains.kotlin.resolve.constants.NullValue import org.jetbrains.kotlin.resolve.constants.StringValue import org.jetbrains.kotlin.resolve.descriptorUtil.nonSourceAnnotations +import org.jetbrains.kotlin.resolve.isInlineClassType import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.contains +import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes import java.util.* class DescriptorSerializer private constructor( @@ -145,6 +147,8 @@ class DescriptorSerializer private constructor( extension.serializeClass(classDescriptor, builder, versionRequirementTable) + writeVersionRequirementForInlineClasses(classDescriptor, builder, versionRequirementTable) + val versionRequirementTableProto = versionRequirementTable.serialize() if (versionRequirementTableProto != null) { builder.versionRequirementTable = versionRequirementTableProto @@ -152,6 +156,28 @@ class DescriptorSerializer private constructor( return builder } + private fun writeVersionRequirementForInlineClasses( + classDescriptor: ClassDescriptor, + builder: ProtoBuf.Class.Builder, + versionRequirementTable: MutableVersionRequirementTable + ) { + if (!classDescriptor.isInline && !classDescriptor.hasInlineClassTypesInSignature()) return + + builder.addVersionRequirement( + DescriptorSerializer.writeLanguageVersionRequirement(LanguageFeature.InlineClasses, versionRequirementTable) + ) + } + + private fun ClassDescriptor.hasInlineClassTypesInSignature(): Boolean { + for (typeParameter in declaredTypeParameters) { + if (typeParameter.upperBounds.any { it.contains(UnwrappedType::isInlineClassType) }) return true + } + + if (defaultType.immediateSupertypes().any { supertype -> supertype.contains(UnwrappedType::isInlineClassType) }) return true + + return false + } + fun propertyProto(descriptor: PropertyDescriptor): ProtoBuf.Property.Builder { val builder = ProtoBuf.Property.newBuilder() @@ -239,6 +265,10 @@ class DescriptorSerializer private constructor( builder.addVersionRequirement(writeVersionRequirementDependingOnCoroutinesVersion()) } + if (descriptor.hasInlineClassTypesInSignature()) { + builder.addVersionRequirement(writeVersionRequirement(LanguageFeature.InlineClasses)) + } + extension.serializeProperty(descriptor, builder, versionRequirementTable) return builder @@ -308,6 +338,10 @@ class DescriptorSerializer private constructor( builder.addVersionRequirement(writeVersionRequirementDependingOnCoroutinesVersion()) } + if (descriptor.hasInlineClassTypesInSignature()) { + builder.addVersionRequirement(writeVersionRequirement(LanguageFeature.InlineClasses)) + } + contractSerializer.serializeContractOfFunctionIfAny(descriptor, builder, this) extension.serializeFunction(descriptor, builder) @@ -337,6 +371,10 @@ class DescriptorSerializer private constructor( builder.addVersionRequirement(writeVersionRequirementDependingOnCoroutinesVersion()) } + if (descriptor.hasInlineClassTypesInSignature()) { + builder.addVersionRequirement(writeVersionRequirement(LanguageFeature.InlineClasses)) + } + extension.serializeConstructor(descriptor, builder) return builder @@ -348,12 +386,20 @@ class DescriptorSerializer private constructor( private fun CallableMemberDescriptor.isSuspendOrHasSuspendTypesInSignature(): Boolean { if (this is FunctionDescriptor && isSuspend) return true + return allTypesFromSignature().any { type -> type.contains(UnwrappedType::isSuspendFunctionTypeOrSubtype) } + } + + private fun CallableMemberDescriptor.hasInlineClassTypesInSignature(): Boolean { + return allTypesFromSignature().any { type -> type.contains(UnwrappedType::isInlineClassType) } + } + + private fun CallableMemberDescriptor.allTypesFromSignature(): List { return listOfNotNull( - extensionReceiverParameter?.type, - returnType, - *typeParameters.flatMap { it.upperBounds }.toTypedArray(), - *valueParameters.map(ValueParameterDescriptor::getType).toTypedArray() - ).any { type -> type.contains(UnwrappedType::isSuspendFunctionTypeOrSubtype) } + extensionReceiverParameter?.type, + returnType, + *typeParameters.flatMap { it.upperBounds }.toTypedArray(), + *valueParameters.map(ValueParameterDescriptor::getType).toTypedArray() + ) } fun typeAliasProto(descriptor: TypeAliasDescriptor): ProtoBuf.TypeAlias.Builder { @@ -614,15 +660,7 @@ class DescriptorSerializer private constructor( } private fun writeVersionRequirement(languageFeature: LanguageFeature): Int { - val languageVersion = languageFeature.sinceVersion!! - return writeVersionRequirement( - languageVersion.major, languageVersion.minor, 0, - ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION - ) - } - - private fun writeVersionRequirement(major: Int, minor: Int, patch: Int, versionKind: ProtoBuf.VersionRequirement.VersionKind): Int { - return writeVersionRequirement(major, minor, patch, versionKind, versionRequirementTable) + return writeLanguageVersionRequirement(languageFeature, versionRequirementTable) } // Returns a list of indices into versionRequirementTable, or empty list if there's no @RequireKotlin on the descriptor @@ -758,6 +796,18 @@ class DescriptorSerializer private constructor( Collections.sort(this, MemberComparator.INSTANCE) } + fun writeLanguageVersionRequirement( + languageFeature: LanguageFeature, + versionRequirementTable: MutableVersionRequirementTable + ): Int { + val languageVersion = languageFeature.sinceVersion!! + return writeVersionRequirement( + languageVersion.major, languageVersion.minor, 0, + ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION, + versionRequirementTable + ) + } + fun writeVersionRequirement( major: Int, minor: Int, diff --git a/compiler/testData/versionRequirement/inlineClassesAndRelevantDeclarations.kt b/compiler/testData/versionRequirement/inlineClassesAndRelevantDeclarations.kt new file mode 100644 index 00000000000..62993fbcfd5 --- /dev/null +++ b/compiler/testData/versionRequirement/inlineClassesAndRelevantDeclarations.kt @@ -0,0 +1,18 @@ +package test + +@Suppress("UNSUPPORTED_FEATURE") +inline class IC(val x: String) + +typealias ICAlias = IC + +class Ctor(ic: IC) + +fun simpleFun(f: IC) {} +fun aliasedFun(f: ICAlias) {} + +val simpleProp: IC = IC("") + +fun result(r: List?>) {} + +abstract class Foo : List +interface Bar diff --git a/compiler/tests/org/jetbrains/kotlin/serialization/AbstractVersionRequirementTest.kt b/compiler/tests/org/jetbrains/kotlin/serialization/AbstractVersionRequirementTest.kt index c6ff006d40f..88bf4478f11 100644 --- a/compiler/tests/org/jetbrains/kotlin/serialization/AbstractVersionRequirementTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/serialization/AbstractVersionRequirementTest.kt @@ -171,4 +171,21 @@ abstract class AbstractVersionRequirementTest : TestCaseWithTmpdir() { ) ) } + + fun testInlineClassesAndRelevantDeclarations() { + doTest( + VersionRequirement.Version(1, 3), DeprecationLevel.ERROR, null, ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION, null, + customLanguageVersion = LanguageVersion.KOTLIN_1_2, + fqNames = listOf( + "test.IC", + "test.Ctor.", + "test.simpleFun", + "test.aliasedFun", + "test.simpleProp", + "test.result", + "test.Foo", + "test.Bar" + ) + ) + } }