From 37813d9d82c5a5ff246dd479dd34f754e44d3305 Mon Sep 17 00:00:00 2001 From: "Denis.Zharkov" Date: Thu, 8 Apr 2021 14:44:44 +0300 Subject: [PATCH] Add version requirements for declarations with !! types ^KT-26245 Related --- .../serialization/DescriptorSerializer.kt | 49 +++++++++++++++++-- .../versionRequirement/definitelyNotNull.kt | 33 +++++++++++++ .../AbstractVersionRequirementTest.kt | 22 +++++++++ 3 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/versionRequirement/definitelyNotNull.kt diff --git a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt index 8742e77378e..96552b10840 100644 --- a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt +++ b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt @@ -50,6 +50,13 @@ class DescriptorSerializer private constructor( ) { private val contractSerializer = ContractSerializer() + private var metDefinitelyNotNullTypeStack: MutableList = mutableListOf(false) + private var metDefinitelyNotNullType: Boolean + get() = metDefinitelyNotNullTypeStack.last() + set(value) { + metDefinitelyNotNullTypeStack[metDefinitelyNotNullTypeStack.lastIndex] = value + } + private fun createChildSerializer(descriptor: DeclarationDescriptor): DescriptorSerializer = DescriptorSerializer( descriptor, Interner(typeParameters), extension, typeTable, versionRequirementTable, @@ -61,7 +68,16 @@ class DescriptorSerializer private constructor( private fun useTypeTable(): Boolean = extension.shouldUseTypeTable() - fun classProto(classDescriptor: ClassDescriptor): ProtoBuf.Class.Builder { + private inline fun withNewMetDefinitelyNotNullType(block: () -> T): T { + metDefinitelyNotNullTypeStack.add(false) + return try { + block() + } finally { + metDefinitelyNotNullTypeStack.removeAt(metDefinitelyNotNullTypeStack.lastIndex) + } + } + + fun classProto(classDescriptor: ClassDescriptor): ProtoBuf.Class.Builder = withNewMetDefinitelyNotNullType { val builder = ProtoBuf.Class.newBuilder() val flags = Flags.getClassFlags( @@ -174,10 +190,17 @@ class DescriptorSerializer private constructor( writeVersionRequirementForInlineClasses(classDescriptor, builder, versionRequirementTable) + if (metDefinitelyNotNullType) { + builder.addVersionRequirement( + writeLanguageVersionRequirement(LanguageFeature.DefinitelyNotNullTypeParameters, versionRequirementTable) + ) + } + val versionRequirementTableProto = versionRequirementTable.serialize() if (versionRequirementTableProto != null) { builder.versionRequirementTable = versionRequirementTableProto } + return builder } @@ -294,6 +317,10 @@ class DescriptorSerializer private constructor( if (descriptor.hasInlineClassTypesInSignature()) { builder.addVersionRequirement(writeVersionRequirement(LanguageFeature.InlineClasses)) } + + if (local.metDefinitelyNotNullType) { + builder.addVersionRequirement(writeVersionRequirement(LanguageFeature.DefinitelyNotNullTypeParameters)) + } } extension.serializeProperty(descriptor, builder, versionRequirementTable, local) @@ -377,6 +404,10 @@ class DescriptorSerializer private constructor( if (descriptor.hasInlineClassTypesInSignature()) { builder.addVersionRequirement(writeVersionRequirement(LanguageFeature.InlineClasses)) } + + if (local.metDefinitelyNotNullType) { + builder.addVersionRequirement(writeVersionRequirement(LanguageFeature.DefinitelyNotNullTypeParameters)) + } } contractSerializer.serializeContractOfFunctionIfAny(descriptor, builder, this) @@ -413,6 +444,10 @@ class DescriptorSerializer private constructor( if (descriptor.hasInlineClassTypesInSignature()) { builder.addVersionRequirement(writeVersionRequirement(LanguageFeature.InlineClasses)) } + + if (local.metDefinitelyNotNullType) { + builder.addVersionRequirement(writeVersionRequirement(LanguageFeature.DefinitelyNotNullTypeParameters)) + } } extension.serializeConstructor(descriptor, builder, local) @@ -442,7 +477,7 @@ class DescriptorSerializer private constructor( ) } - private fun typeAliasProto(descriptor: TypeAliasDescriptor): ProtoBuf.TypeAlias.Builder? { + private fun typeAliasProto(descriptor: TypeAliasDescriptor): ProtoBuf.TypeAlias.Builder? = withNewMetDefinitelyNotNullType { if (!extension.shouldSerializeTypeAlias(descriptor)) return null val builder = ProtoBuf.TypeAlias.newBuilder() @@ -475,6 +510,11 @@ class DescriptorSerializer private constructor( versionRequirementTable?.run { builder.addAllVersionRequirement(serializeVersionRequirements(descriptor)) + if (local.metDefinitelyNotNullType) { + builder.addVersionRequirement( + writeLanguageVersionRequirement(LanguageFeature.DefinitelyNotNullTypeParameters, versionRequirementTable) + ) + } } for (annotation in descriptor.nonSourceAnnotations) { @@ -600,7 +640,10 @@ class DescriptorSerializer private constructor( builder.typeParameter = getTypeParameterId(descriptor) } - builder.flags = Flags.getTypeFlags(false, type is DefinitelyNotNullType) + if (type.unwrap() is DefinitelyNotNullType) { + metDefinitelyNotNullType = true + builder.flags = Flags.getTypeFlags(false, true) + } assert(type.arguments.isEmpty()) { "Found arguments for type constructor build on type parameter: $descriptor" } } diff --git a/compiler/testData/versionRequirement/definitelyNotNull.kt b/compiler/testData/versionRequirement/definitelyNotNull.kt new file mode 100644 index 00000000000..3e98085369c --- /dev/null +++ b/compiler/testData/versionRequirement/definitelyNotNull.kt @@ -0,0 +1,33 @@ +package test + +interface A { + fun foo(x: T!!) + + val w: T!! +} + +class B(r: X!!) + +fun inside() { + object : A { + override fun foo(x: K!!) { + } + + override val w: K!! + get() = TODO("") + } +} + +fun bar1(x: F!!) {} +fun bar2(x: F) = x!! + +val E.nn: E!! get() = this!! + +class Outer { + abstract class R1 : A + abstract class R2 : A + + abstract class W : A +} + +typealias Alias = A diff --git a/compiler/tests/org/jetbrains/kotlin/serialization/AbstractVersionRequirementTest.kt b/compiler/tests/org/jetbrains/kotlin/serialization/AbstractVersionRequirementTest.kt index 2fb39032f46..7a2b8ad93f1 100644 --- a/compiler/tests/org/jetbrains/kotlin/serialization/AbstractVersionRequirementTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/serialization/AbstractVersionRequirementTest.kt @@ -138,6 +138,28 @@ abstract class AbstractVersionRequirementTest : TestCaseWithTmpdir() { ) } + fun testDefinitelyNotNull() { + doTest( + VersionRequirement.Version(1, 6), DeprecationLevel.ERROR, null, ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION, null, + customLanguageVersion = LanguageVersion.KOTLIN_1_6, + fqNamesWithRequirements = listOf( + "test.A.foo", + "test.A.w", + "test.B.", + "test.bar1", + "test.bar2", + "test.nn", + "test.Outer.R1", + "test.Outer.R2", + "test.Alias", + ), + fqNamesWithoutRequirement = listOf( + "test.Outer", + "test.Outer.W", + ), + ) + } + fun testLanguageVersionViaAnnotation() { doTest( VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message",