Add serialization/deserialization of definitely-not-null types

^KT-26245 In Progress
This commit is contained in:
Denis.Zharkov
2021-04-06 17:42:56 +03:00
committed by TeamCityServer
parent 6ca6bb2d45
commit 30eb9ad32f
19 changed files with 98 additions and 11 deletions
@@ -0,0 +1 @@
public final fun <T> foo(x: R|T!!|, y: R|kotlin/collections/List<T!!>|, z: R|(T!!) -> T!!|): R|T!!|
@@ -132,9 +132,16 @@ class FirTypeDeserializer(
fun FirClassLikeSymbol<*>.typeParameters(): List<FirTypeParameterSymbol> =
(fir as? FirTypeParameterRefsOwner)?.typeParameters?.map { it.symbol }.orEmpty()
fun simpleType(proto: ProtoBuf.Type, attributes: ConeAttributes): ConeLookupTagBasedType? {
fun simpleType(proto: ProtoBuf.Type, attributes: ConeAttributes): ConeSimpleKotlinType? {
val constructor = typeSymbol(proto) ?: return null
if (constructor is ConeTypeParameterLookupTag) return ConeTypeParameterTypeImpl(constructor, isNullable = proto.nullable)
if (constructor is ConeTypeParameterLookupTag) {
return ConeTypeParameterTypeImpl(constructor, isNullable = proto.nullable).let {
if (Flags.DEFINITELY_NOT_NULL_TYPE.get(proto.flags))
ConeDefinitelyNotNullType.create(it)
else
it
}
}
if (constructor !is ConeClassLikeLookupTag) return null
fun ProtoBuf.Type.collectAllArguments(): List<ProtoBuf.Type.Argument> =
@@ -598,10 +598,16 @@ class FirElementSerializer private constructor(
}
}
private fun typeProto(type: ConeKotlinType, toSuper: Boolean = false, correspondingTypeRef: FirTypeRef? = null): ProtoBuf.Type.Builder {
private fun typeProto(
type: ConeKotlinType,
toSuper: Boolean = false,
correspondingTypeRef: FirTypeRef? = null,
isDefinitelyNotNullType: Boolean = false,
): ProtoBuf.Type.Builder {
val builder = ProtoBuf.Type.newBuilder()
when (type) {
is ConeDefinitelyNotNullType -> return typeProto(type, toSuper, correspondingTypeRef, isDefinitelyNotNullType = true)
is ConeKotlinErrorType -> {
extension.serializeErrorType(type, builder)
return builder
@@ -623,7 +629,7 @@ class FirElementSerializer private constructor(
session, CONTINUATION_INTERFACE_CLASS_ID
)
val functionType = typeProto(runtimeFunctionType)
functionType.flags = Flags.getTypeFlags(true)
functionType.flags = Flags.getTypeFlags(true, false)
return functionType
}
fillFromPossiblyInnerType(builder, type)
@@ -640,8 +646,11 @@ class FirElementSerializer private constructor(
} else {
builder.typeParameter = getTypeParameterId(typeParameter)
}
if (isDefinitelyNotNullType) {
builder.flags = Flags.getTypeFlags(false, isDefinitelyNotNullType)
}
}
is ConeDefinitelyNotNullType,
is ConeIntersectionType -> {
val approximatedType = if (toSuper) {
typeApproximator.approximateToSuperType(type, TypeApproximatorConfiguration.PublicDeclaration)
@@ -584,7 +584,7 @@ class DescriptorSerializer private constructor(
if (type.isSuspendFunctionType) {
val functionType = type(transformSuspendFunctionToRuntimeFunctionType(type, extension.releaseCoroutines()))
functionType.flags = Flags.getTypeFlags(true)
functionType.flags = Flags.getTypeFlags(true, false)
return functionType
}
@@ -600,6 +600,8 @@ class DescriptorSerializer private constructor(
builder.typeParameter = getTypeParameterId(descriptor)
}
builder.flags = Flags.getTypeFlags(false, type is DefinitelyNotNullType)
assert(type.arguments.isEmpty()) { "Found arguments for type constructor build on type parameter: $descriptor" }
}
}
@@ -0,0 +1,5 @@
// !LANGUAGE: +DefinitelyNotNullTypeParameters
// COMPILER_ARGUMENTS: -XXLanguage:+DefinitelyNotNullTypeParameters
package test
fun <T> foo(x: T!!, y: List<T!!>, z: (T!!) -> T!!): T!! = x
@@ -0,0 +1,3 @@
package test
public fun </*0*/ T> foo(/*0*/ x: T!!, /*1*/ y: kotlin.collections.List<T!!>, /*2*/ z: (T!!) -> T!!): T!!
@@ -2116,6 +2116,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt");
}
@TestMetadata("DefinitelyNotNull.kt")
public void testDefinitelyNotNull() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/DefinitelyNotNull.kt");
}
@TestMetadata("ReceiverParameter.kt")
public void testReceiverParameter() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt");
@@ -438,6 +438,11 @@ public class LoadKotlinWithTypeTableTestGenerated extends AbstractLoadKotlinWith
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt");
}
@TestMetadata("DefinitelyNotNull.kt")
public void testDefinitelyNotNull() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/DefinitelyNotNull.kt");
}
@TestMetadata("ReceiverParameter.kt")
public void testReceiverParameter() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt");
@@ -2117,6 +2117,11 @@ public class IrLoadJavaTestGenerated extends AbstractIrLoadJavaTest {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt");
}
@TestMetadata("DefinitelyNotNull.kt")
public void testDefinitelyNotNull() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/DefinitelyNotNull.kt");
}
@TestMetadata("ReceiverParameter.kt")
public void testReceiverParameter() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt");
@@ -2116,6 +2116,11 @@ public class LoadJavaUsingJavacTestGenerated extends AbstractLoadJavaUsingJavacT
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt");
}
@TestMetadata("DefinitelyNotNull.kt")
public void testDefinitelyNotNull() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/DefinitelyNotNull.kt");
}
@TestMetadata("ReceiverParameter.kt")
public void testReceiverParameter() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt");
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.descriptors.runtime.components.ReflectKotlinClass
import org.jetbrains.kotlin.descriptors.runtime.components.RuntimeModuleData
import org.jetbrains.kotlin.descriptors.runtime.structure.classId
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.jvm.compiler.AbstractLoadJavaTest
import org.jetbrains.kotlin.jvm.compiler.ExpectedLoadErrorsUtil
import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
@@ -131,6 +132,9 @@ abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdir() {
val environment = KotlinTestUtils.createEnvironmentWithJdkAndNullabilityAnnotationsFromIdea(
testRootDisposable, ConfigurationKind.ALL, jdkKind
)
AbstractLoadJavaTest.updateConfigurationWithDirectives(file.readText(), environment.configuration)
for (root in environment.configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS)) {
LOG.info("root: $root")
}
@@ -440,6 +440,11 @@ public class JvmRuntimeDescriptorLoaderTestGenerated extends AbstractJvmRuntimeD
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt");
}
@TestMetadata("DefinitelyNotNull.kt")
public void testDefinitelyNotNull() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/DefinitelyNotNull.kt");
}
@TestMetadata("ReceiverParameter.kt")
public void testReceiverParameter() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt");
@@ -101,7 +101,12 @@ class TypeDeserializer(
Flags.SUSPEND_TYPE.get(proto.flags) ->
createSuspendFunctionType(annotations, constructor, arguments, proto.nullable)
else ->
KotlinTypeFactory.simpleType(annotations, constructor, arguments, proto.nullable)
KotlinTypeFactory.simpleType(annotations, constructor, arguments, proto.nullable).let {
if (Flags.DEFINITELY_NOT_NULL_TYPE.get(proto.flags))
DefinitelyNotNullType.makeDefinitelyNotNull(it) ?: error("null DefinitelyNotNullType for '$it'")
else
it
}
}
val computedType = proto.abbreviatedType(c.typeTable)?.let {
@@ -15,6 +15,7 @@ public class Flags {
// Types
public static final BooleanFlagField SUSPEND_TYPE = FlagField.booleanFirst();
public static final BooleanFlagField DEFINITELY_NOT_NULL_TYPE = FlagField.booleanAfter(SUSPEND_TYPE);
// Common for declarations
@@ -85,8 +86,8 @@ public class Flags {
// ---
public static int getTypeFlags(boolean isSuspend) {
return SUSPEND_TYPE.toFlags(isSuspend);
public static int getTypeFlags(boolean isSuspend, boolean isDefinitelyNotNull) {
return SUSPEND_TYPE.toFlags(isSuspend) | DEFINITELY_NOT_NULL_TYPE.toFlags(isDefinitelyNotNull);
}
public static int getClassFlags(
@@ -74,7 +74,14 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
private fun createTypeParameterStub(parent: KotlinStubBaseImpl<*>, type: Type, name: Name, annotations: List<ClassIdWithTarget>) {
createTypeAnnotationStubs(parent, type, annotations)
createStubForTypeName(ClassId.topLevel(FqName.topLevel(name)), nullableTypeParent(parent, type))
val nullableParentWrapper = nullableTypeParent(parent, type)
val definitelyNotNullTypeWrapper =
if (Flags.DEFINITELY_NOT_NULL_TYPE.get(type.flags))
KotlinPlaceHolderStubImpl<KtNullableType>(parent, KtStubElementTypes.DEFINITELY_NOT_NULL_TYPE)
else
nullableParentWrapper
createStubForTypeName(ClassId.topLevel(FqName.topLevel(name)), definitelyNotNullTypeWrapper)
}
private fun createClassReferenceTypeStub(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<ClassIdWithTarget>) {
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.idea.caches.IDEKotlinBinaryClassCache
import org.jetbrains.kotlin.idea.decompiler.KotlinDecompiledFileViewProvider
import org.jetbrains.kotlin.idea.decompiler.classFile.KotlinClsStubBuilder
import org.jetbrains.kotlin.idea.decompiler.classFile.KtClsFile
import org.jetbrains.kotlin.jvm.compiler.AbstractLoadJavaTest
import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil
import org.jetbrains.kotlin.psi.stubs.elements.KtFileStubBuilder
import org.jetbrains.kotlin.test.ConfigurationKind
@@ -43,6 +44,9 @@ abstract class AbstractLoadJavaClsStubTest : TestCaseWithTmpdir() {
if (useTypeTableInSerializer) {
configuration.put(JVMConfigurationKeys.USE_TYPE_TABLE, true)
}
AbstractLoadJavaTest.updateConfigurationWithDirectives(ktFile.readText(), configuration)
val environment = KotlinCoreEnvironment.createForTests(testRootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
environment.projectEnvironment.environment.application.registerService(
IDEKotlinBinaryClassCache::class.java,
@@ -438,6 +438,11 @@ public class LoadJavaClsStubTestGenerated extends AbstractLoadJavaClsStubTest {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt");
}
@TestMetadata("DefinitelyNotNull.kt")
public void testDefinitelyNotNull() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/DefinitelyNotNull.kt");
}
@TestMetadata("ReceiverParameter.kt")
public void testReceiverParameter() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt");
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
import org.jetbrains.kotlin.idea.test.AstAccessControl
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.withCustomCompilerOptions
import org.jetbrains.kotlin.load.java.descriptors.PossiblyExternalAnnotationDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile
@@ -33,7 +34,10 @@ abstract class AbstractResolveByStubTest : KotlinLightCodeInsightFixtureTestCase
myFixture.configureByFile(fileName)
val shouldFail = getTestName(false) == "ClassWithConstVal"
AstAccessControl.testWithControlledAccessToAst(shouldFail, project, testRootDisposable) {
performTest(testPath())
val path = testPath()
withCustomCompilerOptions(File(path).readText(), project, module) {
performTest(path)
}
}
}
@@ -438,6 +438,11 @@ public class ResolveByStubTestGenerated extends AbstractResolveByStubTest {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt");
}
@TestMetadata("DefinitelyNotNull.kt")
public void testDefinitelyNotNull() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/DefinitelyNotNull.kt");
}
@TestMetadata("ReceiverParameter.kt")
public void testReceiverParameter() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt");