From 1c8587f82dbe3050ee16200ae58ca3b2b76901ce Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Fri, 20 Jan 2023 16:27:45 +0200 Subject: [PATCH] [FIR] Extract functional type kind from annotation on lambda literal --- .../types/FirFunctionalTypeKindServiceImpl.kt | 19 ++++++++--- .../kotlin/fir/resolve/ResolveUtils.kt | 33 ++++++++++++++----- .../fir/resolve/inference/InferenceUtils.kt | 3 +- ...rCallCompletionResultsWriterTransformer.kt | 2 +- .../FirDeclarationsResolveTransformer.kt | 3 +- .../fir/types/FirFunctionalTypeKindService.kt | 6 ++-- 6 files changed, 47 insertions(+), 19 deletions(-) diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/FirFunctionalTypeKindServiceImpl.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/FirFunctionalTypeKindServiceImpl.kt index 9b33efb39cd..f6911cb61d3 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/FirFunctionalTypeKindServiceImpl.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/FirFunctionalTypeKindServiceImpl.kt @@ -13,7 +13,8 @@ import org.jetbrains.kotlin.fir.declarations.utils.isSuspend import org.jetbrains.kotlin.fir.extensions.FirFunctionalTypeKindExtension import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.extensions.functionalTypeKindExtensions -import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.name.ClassId class FirFunctionalTypeKindServiceImpl(private val session: FirSession) : FirFunctionalTypeKindService() { @@ -49,15 +50,25 @@ class FirFunctionalTypeKindServiceImpl(private val session: FirSession) : FirFun FunctionalTypeKindExtractor(kinds) } - override fun extractSingleSpecialKindForFunction(functionSymbol: FirNamedFunctionSymbol): FunctionalTypeKind? { + override fun extractSingleSpecialKindForFunction(functionSymbol: FirFunctionSymbol<*>): FunctionalTypeKind? { if (nonReflectKindsFromExtensions.isEmpty()) { return FunctionalTypeKind.SuspendFunction.takeIf { functionSymbol.isSuspend } } + return extractAllSpecialKindsForFunction(functionSymbol).singleOrNull() } - override fun extractAllSpecialKindsForFunction(functionSymbol: FirNamedFunctionSymbol): List { - return extractSpecialKindsImpl(functionSymbol, { isSuspend }, { resolvedAnnotationClassIds }) + override fun extractAllSpecialKindsForFunction(functionSymbol: FirFunctionSymbol<*>): List { + return extractSpecialKindsImpl( + functionSymbol, + { isSuspend }, + { + when (functionSymbol) { + is FirAnonymousFunctionSymbol -> functionSymbol.annotations.mapNotNull { it.toAnnotationClassId(session) } + else -> resolvedAnnotationClassIds + } + } + ) } override fun extractAllSpecialKindsForFunctionalTypeRef(typeRef: FirFunctionTypeRef): List { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt index 7bb8be2e637..d2ce84d7194 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt @@ -18,10 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.canNarrowDownGetterType import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType import org.jetbrains.kotlin.fir.declarations.utils.isFinal import org.jetbrains.kotlin.fir.declarations.utils.modality -import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic -import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic -import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic -import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind +import org.jetbrains.kotlin.fir.diagnostics.* import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression @@ -119,10 +116,30 @@ fun FirFunction.constructFunctionalType(kind: FunctionalTypeKind? = null): ConeL /** * [kind] == null means that [FunctionalTypeKind.Function] will be used */ -fun FirFunction.constructFunctionalTypeRef(kind: FunctionalTypeKind? = null): FirResolvedTypeRef { - return buildResolvedTypeRef { - source = this@constructFunctionalTypeRef.source?.fakeElement(KtFakeSourceElementKind.ImplicitTypeRef) - type = constructFunctionalType(kind) +fun FirAnonymousFunction.constructFunctionalTypeRef(session: FirSession, kind: FunctionalTypeKind? = null): FirResolvedTypeRef { + var diagnostic: ConeDiagnostic? = null + val kinds = session.functionalTypeService.extractAllSpecialKindsForFunction(symbol) + val kindFromDeclaration = when(kinds.size) { + 0 -> null + 1 -> kinds.single() + else -> { + diagnostic = ConeAmbiguousFunctionalTypeKinds(kinds) + FunctionalTypeKind.Function + } + } + val type = constructFunctionalType(kindFromDeclaration ?: kind) + val source = this@constructFunctionalTypeRef.source?.fakeElement(KtFakeSourceElementKind.ImplicitTypeRef) + return if (diagnostic == null) { + buildResolvedTypeRef { + this.source = source + this.type = type + } + } else { + buildErrorTypeRef { + this.source = source + this.type = type + this.diagnostic = diagnostic + } } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt index 1dfcb602a80..cb80da55462 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt @@ -37,6 +37,7 @@ fun extractLambdaInfoFromFunctionalType( ) } val expectedFunctionalKind = expectedType.functionalTypeKind(session) ?: return null + val actualFunctionalKind = session.functionalTypeService.extractSingleSpecialKindForFunction(argument.symbol) val singleStatement = argument.body?.statements?.singleOrNull() as? FirReturnExpression if (argument.returnType == null && singleStatement != null && @@ -100,7 +101,7 @@ fun extractLambdaInfoFromFunctionalType( return ResolvedLambdaAtom( argument, expectedType, - expectedFunctionalKind, + actualFunctionalKind ?: expectedFunctionalKind, receiverType, contextReceivers, parameters, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt index 45b594a3692..feba21d2221 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt @@ -619,7 +619,7 @@ class FirCallCompletionResultsWriterTransformer( if (needUpdateLambdaType) { val kind = expectedType?.functionalTypeKind(session) ?: result.typeRef.coneTypeSafe()?.functionalTypeKind(session) - result.replaceTypeRef(result.constructFunctionalTypeRef(kind)) + result.replaceTypeRef(result.constructFunctionalTypeRef(session, kind)) session.lookupTracker?.recordTypeResolveAsLookup(result.typeRef, result.source, context.file.source) } // Have to delay this until the type is written to avoid adding a return if the type is Unit. diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index febda3d0848..b72fbb00ff2 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -714,6 +714,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve data: ResolutionMode ): FirStatement = whileAnalysing(session, anonymousFunction) { // Either ContextDependent, ContextIndependent or WithExpectedType could be here + anonymousFunction.transformAnnotations(transformer, ResolutionMode.ContextIndependent) if (data !is ResolutionMode.LambdaResolution) { anonymousFunction.transformReturnTypeRef(transformer, ResolutionMode.ContextIndependent) anonymousFunction.transformReceiverParameter(transformer, ResolutionMode.ContextIndependent) @@ -805,7 +806,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve session.lookupTracker?.recordTypeResolveAsLookup(lambda.returnTypeRef, lambda.source, context.file.source) } - lambda.replaceTypeRef(lambda.constructFunctionalTypeRef(resolvedLambdaAtom?.expectedFunctionalTypeKind)) + lambda.replaceTypeRef(lambda.constructFunctionalTypeRef(session, resolvedLambdaAtom?.expectedFunctionalTypeKind)) session.lookupTracker?.recordTypeResolveAsLookup(lambda.typeRef, lambda.source, context.file.source) lambda.addReturnToLastStatementIfNeeded() return lambda diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirFunctionalTypeKindService.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirFunctionalTypeKindService.kt index a55b4ffbf38..3a05ff261c4 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirFunctionalTypeKindService.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirFunctionalTypeKindService.kt @@ -10,7 +10,6 @@ import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKindExtractor import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSessionComponent import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.name.FqName abstract class FirFunctionalTypeKindService : FirSessionComponent { @@ -24,9 +23,8 @@ abstract class FirFunctionalTypeKindService : FirSessionComponent { return extractor.hasKindWithSpecificPackage(packageFqName) } - abstract fun extractSingleSpecialKindForFunction(functionSymbol: FirNamedFunctionSymbol): FunctionalTypeKind? - abstract fun extractAllSpecialKindsForFunction(functionSymbol: FirNamedFunctionSymbol): List - + abstract fun extractSingleSpecialKindForFunction(functionSymbol: FirFunctionSymbol<*>): FunctionalTypeKind? + abstract fun extractAllSpecialKindsForFunction(functionSymbol: FirFunctionSymbol<*>): List abstract fun extractAllSpecialKindsForFunctionalTypeRef(typeRef: FirFunctionTypeRef): List }