Add version requirements for declarations with !! types

^KT-26245 Related
This commit is contained in:
Denis.Zharkov
2021-04-08 14:44:44 +03:00
committed by TeamCityServer
parent 403406f92d
commit 37813d9d82
3 changed files with 101 additions and 3 deletions
@@ -50,6 +50,13 @@ class DescriptorSerializer private constructor(
) {
private val contractSerializer = ContractSerializer()
private var metDefinitelyNotNullTypeStack: MutableList<Boolean> = 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 <T> 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" }
}
@@ -0,0 +1,33 @@
package test
interface A<T> {
fun foo(x: T!!)
val w: T!!
}
class B<X>(r: X!!)
fun <K> inside() {
object : A<K> {
override fun foo(x: K!!) {
}
override val w: K!!
get() = TODO("")
}
}
fun <F> bar1(x: F!!) {}
fun <F> bar2(x: F) = x!!
val <E> E.nn: E!! get() = this!!
class Outer {
abstract class R1<T, F : T!!> : A<T!!>
abstract class R2<T, F : T!!> : A<T>
abstract class W<T> : A<T>
}
typealias Alias<R> = A<R!!>
@@ -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.<init>",
"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",