From 336b6ba9f0ee9cfce5b38f0ab0cf70f57c0656da Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Wed, 22 Mar 2023 11:27:31 +0200 Subject: [PATCH] [FIR] Extract extension functional type from an annotated functional type during deserialization ^KT-57140 Fixed --- .../fir/session/FirAbstractSessionFactory.kt | 2 +- .../deserialization/FirTypeDeserializer.kt | 27 ++++++++++++--- .../types/FirFunctionTypeKindServiceImpl.kt | 34 +++++++++++++++---- .../fir/types/FirFunctionTypeKindService.kt | 3 ++ ...endencyWithoutFunctionalKindPlugin.fir.txt | 14 ++++---- .../dependencyWithoutFunctionalKindPlugin.kt | 10 +++--- 6 files changed, 67 insertions(+), 23 deletions(-) diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirAbstractSessionFactory.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirAbstractSessionFactory.kt index fe42399c1b7..5998a704142 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirAbstractSessionFactory.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirAbstractSessionFactory.kt @@ -47,7 +47,6 @@ abstract class FirAbstractSessionFactory { registerCliCompilerOnlyComponents() registerCommonComponents(languageVersionSettings) - registerCommonComponentsAfterExtensionsAreConfigured() registerExtraComponents(this) val kotlinScopeProvider = createKotlinScopeProvider.invoke() @@ -65,6 +64,7 @@ abstract class FirAbstractSessionFactory { registerExtensions(extensionRegistrar.configure()) } }.configure() + registerCommonComponentsAfterExtensionsAreConfigured() val providers = createProviders(this, builtinsModuleData, kotlinScopeProvider) diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirTypeDeserializer.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirTypeDeserializer.kt index da8c653e032..47aa6231848 100644 --- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirTypeDeserializer.kt +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirTypeDeserializer.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol import org.jetbrains.kotlin.fir.types.* @@ -176,10 +177,28 @@ class FirTypeDeserializer( argumentList + outerType(typeTable)?.collectAllArguments().orEmpty() val arguments = proto.collectAllArguments().map(this::typeArgument).toTypedArray() - val simpleType = if (Flags.SUSPEND_TYPE.get(proto.flags)) { - createSuspendFunctionType(constructor, arguments, isNullable = proto.nullable, attributes) - } else { - ConeClassLikeTypeImpl(constructor, arguments, isNullable = proto.nullable, attributes) + + val extensionFunctionalKind = moduleData.session.functionTypeService.extractSingleExtensionKindForDeserializedConeType( + constructor.classId, attributes.customAnnotations + ) + + val simpleType = when { + extensionFunctionalKind != null -> { + val newConstructor = if (arguments.isNotEmpty()) { + ConeClassLikeLookupTagImpl(extensionFunctionalKind.numberedClassId(arguments.size - 1)) + } else { + return ConeErrorType( + ConeSimpleDiagnostic("Illegal number of arguments for extension functional type $extensionFunctionalKind"), + typeArguments = arguments, + attributes = attributes + ) + } + ConeClassLikeTypeImpl(newConstructor, arguments, isNullable = proto.nullable, attributes) + } + Flags.SUSPEND_TYPE.get(proto.flags) -> { + createSuspendFunctionType(constructor, arguments, isNullable = proto.nullable, attributes) + } + else -> ConeClassLikeTypeImpl(constructor, arguments, isNullable = proto.nullable, attributes) } val abbreviatedTypeProto = proto.abbreviatedType(typeTable) ?: return simpleType return simpleType(abbreviatedTypeProto, attributes) diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/FirFunctionTypeKindServiceImpl.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/FirFunctionTypeKindServiceImpl.kt index 67b63477b22..c4e9844061c 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/FirFunctionTypeKindServiceImpl.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/FirFunctionTypeKindServiceImpl.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.builtins.functions.FunctionTypeKindExtractor import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId import org.jetbrains.kotlin.fir.declarations.utils.isSuspend +import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.extensions.FirFunctionTypeKindExtension import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.extensions.functionTypeKindExtensions @@ -75,6 +76,23 @@ class FirFunctionTypeKindServiceImpl(private val session: FirSession) : FirFunct return extractSpecialKindsImpl(typeRef, { isSuspend }, { annotations.mapNotNull { it.toAnnotationClassId(session) } }) } + override fun extractSingleExtensionKindForDeserializedConeType( + classId: ClassId, + annotations: List + ): FunctionTypeKind? { + if (nonReflectKindsFromExtensions.isEmpty() || annotations.isEmpty()) return null + val baseKind = extractor.getFunctionalClassKind(classId.packageFqName, classId.shortClassName.asString()) ?: return null + if (baseKind.nonReflectKind() != FunctionTypeKind.Function) return null + val matchingExtensionKinds = buildList { + extractKindsFromAnnotations(annotations.mapNotNull { it.toAnnotationClassId(session) }) + } + val matchingKind = matchingExtensionKinds.singleOrNull() ?: return null + return when (baseKind.isReflectType) { + false -> matchingKind + true -> matchingKind.reflectKind() + } + } + private inline fun extractSpecialKindsImpl( source: T, isSuspend: T.() -> Boolean, @@ -85,12 +103,16 @@ class FirFunctionTypeKindServiceImpl(private val session: FirSession) : FirFunct add(FunctionTypeKind.SuspendFunction) } if (nonReflectKindsFromExtensions.isNotEmpty()) { - for (annotationClassId in source.annotations()) { - for (kind in nonReflectKindsFromExtensions) { - if (kind.annotationOnInvokeClassId == annotationClassId) { - add(kind) - } - } + extractKindsFromAnnotations(source.annotations()) + } + } + } + + private fun MutableList.extractKindsFromAnnotations(annotations: List) { + for (annotationClassId in annotations) { + for (kind in nonReflectKindsFromExtensions) { + if (kind.annotationOnInvokeClassId == annotationClassId) { + add(kind) } } } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirFunctionTypeKindService.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirFunctionTypeKindService.kt index 082b103120f..6bf1fe669fd 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirFunctionTypeKindService.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirFunctionTypeKindService.kt @@ -9,7 +9,9 @@ import org.jetbrains.kotlin.builtins.functions.FunctionTypeKind import org.jetbrains.kotlin.builtins.functions.FunctionTypeKindExtractor import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSessionComponent +import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName abstract class FirFunctionTypeKindService : FirSessionComponent { @@ -36,6 +38,7 @@ abstract class FirFunctionTypeKindService : FirSessionComponent { abstract fun extractSingleSpecialKindForFunction(functionSymbol: FirFunctionSymbol<*>): FunctionTypeKind? abstract fun extractAllSpecialKindsForFunction(functionSymbol: FirFunctionSymbol<*>): List abstract fun extractAllSpecialKindsForFunctionTypeRef(typeRef: FirFunctionTypeRef): List + abstract fun extractSingleExtensionKindForDeserializedConeType(classId: ClassId, annotations: List): FunctionTypeKind? } val FirSession.functionTypeService: FirFunctionTypeKindService by FirSession.sessionComponentAccessor() diff --git a/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/dependencyWithoutFunctionalKindPlugin.fir.txt b/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/dependencyWithoutFunctionalKindPlugin.fir.txt index 6a3d873c02b..86c422ee27a 100644 --- a/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/dependencyWithoutFunctionalKindPlugin.fir.txt +++ b/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/dependencyWithoutFunctionalKindPlugin.fir.txt @@ -7,20 +7,20 @@ FILE: dependencyWithoutFunctionalKindPlugin.kt } public final fun test_1(block: R|() -> kotlin/Unit|, composableBlock: R|@R|org/jetbrains/kotlin/fir/plugin/MyComposable|() some/MyComposableFunction0|, suspendBlock: R|suspend () -> kotlin/Unit|): R|kotlin/Unit| { R|org/jetbrains/kotlin/fir/plugin/consumeComposableFunction|(R|/block|) - R|org/jetbrains/kotlin/fir/plugin/consumeComposableFunction#|(R|/composableBlock|) + R|org/jetbrains/kotlin/fir/plugin/consumeComposableFunction|(R|/composableBlock|) R|org/jetbrains/kotlin/fir/plugin/consumeComposableFunction#|(R|/suspendBlock|) } public final fun test_2(): R|kotlin/Unit| { - lval block: R|() -> kotlin/Unit| = R|org/jetbrains/kotlin/fir/plugin/produceComposableFunction|() - R|/consumeRegularFunction|(R|/block|) - R|/consumeSuspendFunction|(R|/block|) + lval block: R|@R|org/jetbrains/kotlin/fir/plugin/MyComposable|() some/MyComposableFunction0| = R|org/jetbrains/kotlin/fir/plugin/produceComposableFunction|() + R|/consumeRegularFunction#|(R|/block|) + R|/consumeSuspendFunction#|(R|/block|) R|/consumeOurComposableFunction|(R|/block|) R|org/jetbrains/kotlin/fir/plugin/consumeComposableFunction|(R|/block|) } public final fun test_3(): R|kotlin/Unit| { - lval block: R|() -> kotlin/Unit| = R|org/jetbrains/kotlin/fir/plugin/produceBoxedComposableFunction|().R|SubstitutionOverride kotlin/Unit|>| - R|/consumeRegularFunction|(R|/block|) - R|/consumeSuspendFunction|(R|/block|) + lval block: R|@R|org/jetbrains/kotlin/fir/plugin/MyComposable|() some/MyComposableFunction0| = R|org/jetbrains/kotlin/fir/plugin/produceBoxedComposableFunction|().R|SubstitutionOverride|>| + R|/consumeRegularFunction#|(R|/block|) + R|/consumeSuspendFunction#|(R|/block|) R|/consumeOurComposableFunction|(R|/block|) R|org/jetbrains/kotlin/fir/plugin/consumeComposableFunction|(R|/block|) } diff --git a/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/dependencyWithoutFunctionalKindPlugin.kt b/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/dependencyWithoutFunctionalKindPlugin.kt index 6823d46d392..2c5a4ce0868 100644 --- a/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/dependencyWithoutFunctionalKindPlugin.kt +++ b/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/dependencyWithoutFunctionalKindPlugin.kt @@ -10,22 +10,22 @@ fun test_1( suspendBlock: suspend () -> Unit, ) { consumeComposableFunction(block) - consumeComposableFunction(composableBlock) + consumeComposableFunction(composableBlock) consumeComposableFunction(suspendBlock) // should be error } fun test_2() { val block = produceComposableFunction() - consumeRegularFunction(block) // should be error - consumeSuspendFunction(block) // should be error + consumeRegularFunction(block) // should be error + consumeSuspendFunction(block) // should be error consumeOurComposableFunction(block) consumeComposableFunction(block) } fun test_3() { val block = produceBoxedComposableFunction().value - consumeRegularFunction(block) // should be error - consumeSuspendFunction(block) // should be error + consumeRegularFunction(block) // should be error + consumeSuspendFunction(block) // should be error consumeOurComposableFunction(block) consumeComposableFunction(block) }