[FIR] Introduce ConeFunctionalTypeKind as a replacement of FunctionClassKind

This is needed to provide an ability to extend different kinds of
  functional types

Also, cleanup and rename utilities related to functional types to avoid
  possible confusions
This commit is contained in:
Dmitriy Novozhilov
2023-01-18 14:12:11 +02:00
committed by Space Team
parent c98c8d3682
commit c86495dcae
40 changed files with 583 additions and 365 deletions
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.isAbstract
import org.jetbrains.kotlin.fir.declarations.utils.isInline
import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.isSuspendOrKSuspendFunctionType
import org.jetbrains.kotlin.fir.types.isSuspendFunctionType
import org.jetbrains.kotlin.name.JvmNames.SYNCHRONIZED_ANNOTATION_CLASS_ID
object FirSynchronizedAnnotationChecker : FirFunctionChecker() {
@@ -33,7 +33,7 @@ object FirSynchronizedAnnotationChecker : FirFunctionChecker() {
return
}
if (declaration.isSuspend ||
(declaration as? FirAnonymousFunction)?.typeRef?.coneType?.isSuspendOrKSuspendFunctionType(session) == true
(declaration as? FirAnonymousFunction)?.typeRef?.coneType?.isSuspendFunctionType(session) == true
) {
reporter.reportOn(annotation.source, FirJvmErrors.SYNCHRONIZED_ON_SUSPEND, context)
return
@@ -46,4 +46,4 @@ object FirSynchronizedAnnotationChecker : FirFunctionChecker() {
reporter.reportOn(annotation.source, FirJvmErrors.SYNCHRONIZED_ON_ABSTRACT, context)
}
}
}
}
@@ -278,7 +278,7 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() {
}
private fun FirTypeRef?.isFunctionalTypeRef(session: FirSession): Boolean {
return this?.coneType?.isBuiltinFunctionalType(session) == true
return this?.coneType?.isSomeFunctionalType(session) == true
}
private fun FirContractDescription?.getParameterCallsEffectDeclaration(index: Int): ConeCallsEffectDeclaration? {
@@ -144,7 +144,7 @@ internal fun checkConstantArguments(
}
expression is FirQualifiedAccessExpression -> {
val expressionType = expression.typeRef.coneType
if (expressionType.isKFunctionType(session) || expressionType.isKProperty(session) || expressionType.isKMutableProperty(session)) {
if (expressionType.isReflectFunctionalType(session) || expressionType.isKProperty(session) || expressionType.isKMutableProperty(session)) {
return checkConstantArguments(expression.dispatchReceiver, session)
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.builtins.StandardNames.BACKING_FIELD
import org.jetbrains.kotlin.builtins.functions.isSuspendType
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
import org.jetbrains.kotlin.descriptors.Visibilities
@@ -61,7 +62,7 @@ abstract class FirInlineDeclarationChecker : FirFunctionChecker() {
val inalienableParameters = function.valueParameters.filter {
if (it.isNoinline) return@filter false
val type = it.returnTypeRef.coneType
!type.isMarkedNullable && type.isFunctionalType(context.session) { kind -> !kind.isReflectType }
!type.isMarkedNullable && type.isNonReflectFunctionalType(context.session)
}.map { it.symbol }
val visitor = inlineVisitor(
@@ -233,7 +234,7 @@ abstract class FirInlineDeclarationChecker : FirFunctionChecker() {
// TODO: receivers are currently not inline (KT-5837)
// if (targetSymbol.isInline) return true
return targetSymbol.name == OperatorNameConventions.INVOKE &&
targetSymbol.dispatchReceiverType?.isBuiltinFunctionalType(session) == true
targetSymbol.dispatchReceiverType?.isSomeFunctionalType(session) == true
}
private fun checkQualifiedAccess(
@@ -404,8 +405,9 @@ abstract class FirInlineDeclarationChecker : FirFunctionChecker() {
) {
for (param in function.valueParameters) {
val coneType = param.returnTypeRef.coneType
val isFunctionalType = coneType.isFunctionalType(context.session)
val isSuspendFunctionalType = coneType.isSuspendOrKSuspendFunctionType(context.session)
val functionalKind = coneType.functionalTypeKind(context.session)
val isFunctionalType = functionalKind != null
val isSuspendFunctionalType = functionalKind?.isSuspendType == true
val defaultValue = param.defaultValue
if (!(isFunctionalType || isSuspendFunctionalType) && (param.isNoinline || param.isCrossinline)) {
@@ -488,7 +490,7 @@ abstract class FirInlineDeclarationChecker : FirFunctionChecker() {
function.valueParameters.any { param ->
val type = param.returnTypeRef.coneType
!param.isNoinline && !type.isNullable
&& (type.isFunctionalType(session) || type.isSuspendOrKSuspendFunctionType(session))
&& (type.isSimpleFunctionType(session) || type.isSuspendFunctionType(session))
}
if (hasInlinableParameters) return
if (function.isInlineOnly(session)) return
@@ -130,7 +130,7 @@ object FirSuspendCallChecker : FirQualifiedAccessExpressionChecker() {
private fun findEnclosingSuspendFunction(context: CheckerContext): FirFunction? {
return context.containingDeclarations.lastOrNull {
when (it) {
is FirAnonymousFunction -> it.typeRef.coneType.isSuspendOrKSuspendFunctionType(context.session)
is FirAnonymousFunction -> it.typeRef.coneType.isSuspendFunctionType(context.session)
is FirSimpleFunction -> it.isSuspend
else -> false
}
@@ -218,7 +218,7 @@ object FirSuspendCallChecker : FirQualifiedAccessExpressionChecker() {
calledDeclarationSymbol: FirCallableSymbol<*>
): Triple<FirExpression?, FirExpression?, ConeKotlinType?> {
if (this is FirImplicitInvokeCall &&
dispatchReceiver != FirNoReceiverExpression && dispatchReceiver.typeRef.coneType.isSuspendOrKSuspendFunctionType(session)
dispatchReceiver != FirNoReceiverExpression && dispatchReceiver.typeRef.coneType.isSuspendFunctionType(session)
) {
val variableForInvoke = dispatchReceiver
val variableForInvokeType = variableForInvoke.typeRef.coneType
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.isFunctionalType
import org.jetbrains.kotlin.fir.types.isSimpleFunctionType
object UnusedChecker : AbstractFirPropertyInitializationChecker() {
override fun analyze(data: PropertyInitializationInfoData, reporter: DiagnosticReporter, context: CheckerContext) {
@@ -278,7 +278,7 @@ object UnusedChecker : AbstractFirPropertyInitializationChecker() {
val reference = node.fir.calleeReference.resolved ?: return dataForNode
val functionSymbol = reference.resolvedSymbol as? FirFunctionSymbol<*> ?: return dataForNode
val symbol = if (functionSymbol.callableId.callableName.identifier == "invoke") {
localProperties.find { it.name == reference.name && it.resolvedReturnTypeRef.coneType.isFunctionalType(session) }
localProperties.find { it.name == reference.name && it.resolvedReturnTypeRef.coneType.isSimpleFunctionType(session) }
} else null
symbol ?: return dataForNode
@@ -7,15 +7,15 @@ package org.jetbrains.kotlin.fir.analysis.checkers.type
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.getAllowedAnnotationTargets
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.isBuiltinFunctionalType
import org.jetbrains.kotlin.fir.types.isSomeFunctionalType
import org.jetbrains.kotlin.name.StandardClassIds
object FirTypeAnnotationChecker : FirTypeRefChecker() {
@@ -33,7 +33,7 @@ object FirTypeAnnotationChecker : FirTypeRefChecker() {
}
}
if (annotation.toAnnotationClassId(context.session) == StandardClassIds.Annotations.ExtensionFunctionType) {
if (!typeRef.type.isBuiltinFunctionalType(context.session)) {
if (!typeRef.type.isSomeFunctionalType(context.session)) {
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ForbidExtensionFunctionTypeOnNonFunctionTypes)) {
reporter.reportOn(annotation.source, FirErrors.WRONG_EXTENSION_FUNCTION_TYPE, context)
} else {