[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:
committed by
Space Team
parent
c98c8d3682
commit
c86495dcae
+8
-1
@@ -33,7 +33,14 @@ internal class KtFirTypeInfoProvider(
|
|||||||
|
|
||||||
override fun getFunctionClassKind(type: KtType): FunctionClassKind? {
|
override fun getFunctionClassKind(type: KtType): FunctionClassKind? {
|
||||||
val coneType = (type as KtFirType).coneType
|
val coneType = (type as KtFirType).coneType
|
||||||
return coneType.functionClassKind(analysisSession.useSiteSession)
|
return when (coneType.functionalTypeKind(analysisSession.useSiteSession)) {
|
||||||
|
ConeFunctionalTypeKind.Function -> FunctionClassKind.Function
|
||||||
|
ConeFunctionalTypeKind.KFunction -> FunctionClassKind.KFunction
|
||||||
|
ConeFunctionalTypeKind.SuspendFunction -> FunctionClassKind.SuspendFunction
|
||||||
|
ConeFunctionalTypeKind.KSuspendFunction -> FunctionClassKind.KSuspendFunction
|
||||||
|
null -> null
|
||||||
|
else -> null // TODO: consider handling of custom functional type kinds from plugins
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun canBeNull(type: KtType): Boolean = (type as KtFirType).coneType.canBeNull
|
override fun canBeNull(type: KtType): Boolean = (type as KtFirType).coneType.canBeNull
|
||||||
|
|||||||
+3
-2
@@ -49,9 +49,10 @@ internal class KtFirFunctionalType(
|
|||||||
|
|
||||||
override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
|
override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
|
||||||
|
|
||||||
override val isSuspend: Boolean get() = withValidityAssertion { coneType.isSuspendOrKSuspendFunctionType(builder.rootSession) }
|
override val isSuspend: Boolean get() = withValidityAssertion { coneType.isSuspendFunctionType(builder.rootSession) }
|
||||||
|
|
||||||
override val isReflectType: Boolean get() = withValidityAssertion { coneType.isKFunctionType(builder.rootSession) }
|
override val isReflectType: Boolean
|
||||||
|
get() = withValidityAssertion { coneType.functionalTypeKind(builder.rootSession)?.isReflectType == true }
|
||||||
|
|
||||||
override val arity: Int
|
override val arity: Int
|
||||||
get() = withValidityAssertion {
|
get() = withValidityAssertion {
|
||||||
|
|||||||
+2
-2
@@ -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.isInline
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
|
import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
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
|
import org.jetbrains.kotlin.name.JvmNames.SYNCHRONIZED_ANNOTATION_CLASS_ID
|
||||||
|
|
||||||
object FirSynchronizedAnnotationChecker : FirFunctionChecker() {
|
object FirSynchronizedAnnotationChecker : FirFunctionChecker() {
|
||||||
@@ -33,7 +33,7 @@ object FirSynchronizedAnnotationChecker : FirFunctionChecker() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (declaration.isSuspend ||
|
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)
|
reporter.reportOn(annotation.source, FirJvmErrors.SYNCHRONIZED_ON_SUSPEND, context)
|
||||||
return
|
return
|
||||||
|
|||||||
+1
-1
@@ -278,7 +278,7 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun FirTypeRef?.isFunctionalTypeRef(session: FirSession): Boolean {
|
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? {
|
private fun FirContractDescription?.getParameterCallsEffectDeclaration(index: Int): ConeCallsEffectDeclaration? {
|
||||||
|
|||||||
+1
-1
@@ -144,7 +144,7 @@ internal fun checkConstantArguments(
|
|||||||
}
|
}
|
||||||
expression is FirQualifiedAccessExpression -> {
|
expression is FirQualifiedAccessExpression -> {
|
||||||
val expressionType = expression.typeRef.coneType
|
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)
|
return checkConstantArguments(expression.dispatchReceiver, session)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-5
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.KtSourceElement
|
import org.jetbrains.kotlin.KtSourceElement
|
||||||
import org.jetbrains.kotlin.builtins.StandardNames.BACKING_FIELD
|
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.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
@@ -61,7 +62,7 @@ abstract class FirInlineDeclarationChecker : FirFunctionChecker() {
|
|||||||
val inalienableParameters = function.valueParameters.filter {
|
val inalienableParameters = function.valueParameters.filter {
|
||||||
if (it.isNoinline) return@filter false
|
if (it.isNoinline) return@filter false
|
||||||
val type = it.returnTypeRef.coneType
|
val type = it.returnTypeRef.coneType
|
||||||
!type.isMarkedNullable && type.isFunctionalType(context.session) { kind -> !kind.isReflectType }
|
!type.isMarkedNullable && type.isNonReflectFunctionalType(context.session)
|
||||||
}.map { it.symbol }
|
}.map { it.symbol }
|
||||||
|
|
||||||
val visitor = inlineVisitor(
|
val visitor = inlineVisitor(
|
||||||
@@ -233,7 +234,7 @@ abstract class FirInlineDeclarationChecker : FirFunctionChecker() {
|
|||||||
// TODO: receivers are currently not inline (KT-5837)
|
// TODO: receivers are currently not inline (KT-5837)
|
||||||
// if (targetSymbol.isInline) return true
|
// if (targetSymbol.isInline) return true
|
||||||
return targetSymbol.name == OperatorNameConventions.INVOKE &&
|
return targetSymbol.name == OperatorNameConventions.INVOKE &&
|
||||||
targetSymbol.dispatchReceiverType?.isBuiltinFunctionalType(session) == true
|
targetSymbol.dispatchReceiverType?.isSomeFunctionalType(session) == true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkQualifiedAccess(
|
private fun checkQualifiedAccess(
|
||||||
@@ -404,8 +405,9 @@ abstract class FirInlineDeclarationChecker : FirFunctionChecker() {
|
|||||||
) {
|
) {
|
||||||
for (param in function.valueParameters) {
|
for (param in function.valueParameters) {
|
||||||
val coneType = param.returnTypeRef.coneType
|
val coneType = param.returnTypeRef.coneType
|
||||||
val isFunctionalType = coneType.isFunctionalType(context.session)
|
val functionalKind = coneType.functionalTypeKind(context.session)
|
||||||
val isSuspendFunctionalType = coneType.isSuspendOrKSuspendFunctionType(context.session)
|
val isFunctionalType = functionalKind != null
|
||||||
|
val isSuspendFunctionalType = functionalKind?.isSuspendType == true
|
||||||
val defaultValue = param.defaultValue
|
val defaultValue = param.defaultValue
|
||||||
|
|
||||||
if (!(isFunctionalType || isSuspendFunctionalType) && (param.isNoinline || param.isCrossinline)) {
|
if (!(isFunctionalType || isSuspendFunctionalType) && (param.isNoinline || param.isCrossinline)) {
|
||||||
@@ -488,7 +490,7 @@ abstract class FirInlineDeclarationChecker : FirFunctionChecker() {
|
|||||||
function.valueParameters.any { param ->
|
function.valueParameters.any { param ->
|
||||||
val type = param.returnTypeRef.coneType
|
val type = param.returnTypeRef.coneType
|
||||||
!param.isNoinline && !type.isNullable
|
!param.isNoinline && !type.isNullable
|
||||||
&& (type.isFunctionalType(session) || type.isSuspendOrKSuspendFunctionType(session))
|
&& (type.isSimpleFunctionType(session) || type.isSuspendFunctionType(session))
|
||||||
}
|
}
|
||||||
if (hasInlinableParameters) return
|
if (hasInlinableParameters) return
|
||||||
if (function.isInlineOnly(session)) return
|
if (function.isInlineOnly(session)) return
|
||||||
|
|||||||
+2
-2
@@ -130,7 +130,7 @@ object FirSuspendCallChecker : FirQualifiedAccessExpressionChecker() {
|
|||||||
private fun findEnclosingSuspendFunction(context: CheckerContext): FirFunction? {
|
private fun findEnclosingSuspendFunction(context: CheckerContext): FirFunction? {
|
||||||
return context.containingDeclarations.lastOrNull {
|
return context.containingDeclarations.lastOrNull {
|
||||||
when (it) {
|
when (it) {
|
||||||
is FirAnonymousFunction -> it.typeRef.coneType.isSuspendOrKSuspendFunctionType(context.session)
|
is FirAnonymousFunction -> it.typeRef.coneType.isSuspendFunctionType(context.session)
|
||||||
is FirSimpleFunction -> it.isSuspend
|
is FirSimpleFunction -> it.isSuspend
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
@@ -218,7 +218,7 @@ object FirSuspendCallChecker : FirQualifiedAccessExpressionChecker() {
|
|||||||
calledDeclarationSymbol: FirCallableSymbol<*>
|
calledDeclarationSymbol: FirCallableSymbol<*>
|
||||||
): Triple<FirExpression?, FirExpression?, ConeKotlinType?> {
|
): Triple<FirExpression?, FirExpression?, ConeKotlinType?> {
|
||||||
if (this is FirImplicitInvokeCall &&
|
if (this is FirImplicitInvokeCall &&
|
||||||
dispatchReceiver != FirNoReceiverExpression && dispatchReceiver.typeRef.coneType.isSuspendOrKSuspendFunctionType(session)
|
dispatchReceiver != FirNoReceiverExpression && dispatchReceiver.typeRef.coneType.isSuspendFunctionType(session)
|
||||||
) {
|
) {
|
||||||
val variableForInvoke = dispatchReceiver
|
val variableForInvoke = dispatchReceiver
|
||||||
val variableForInvokeType = variableForInvoke.typeRef.coneType
|
val variableForInvokeType = variableForInvoke.typeRef.coneType
|
||||||
|
|||||||
+2
-2
@@ -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.impl.FirPropertySymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
import org.jetbrains.kotlin.fir.types.isFunctionalType
|
import org.jetbrains.kotlin.fir.types.isSimpleFunctionType
|
||||||
|
|
||||||
object UnusedChecker : AbstractFirPropertyInitializationChecker() {
|
object UnusedChecker : AbstractFirPropertyInitializationChecker() {
|
||||||
override fun analyze(data: PropertyInitializationInfoData, reporter: DiagnosticReporter, context: CheckerContext) {
|
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 reference = node.fir.calleeReference.resolved ?: return dataForNode
|
||||||
val functionSymbol = reference.resolvedSymbol as? FirFunctionSymbol<*> ?: return dataForNode
|
val functionSymbol = reference.resolvedSymbol as? FirFunctionSymbol<*> ?: return dataForNode
|
||||||
val symbol = if (functionSymbol.callableId.callableName.identifier == "invoke") {
|
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
|
} else null
|
||||||
symbol ?: return dataForNode
|
symbol ?: return dataForNode
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -7,15 +7,15 @@ package org.jetbrains.kotlin.fir.analysis.checkers.type
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
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.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.getAllowedAnnotationTargets
|
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.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
|
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
|
||||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
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
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
|
|
||||||
object FirTypeAnnotationChecker : FirTypeRefChecker() {
|
object FirTypeAnnotationChecker : FirTypeRefChecker() {
|
||||||
@@ -33,7 +33,7 @@ object FirTypeAnnotationChecker : FirTypeRefChecker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (annotation.toAnnotationClassId(context.session) == StandardClassIds.Annotations.ExtensionFunctionType) {
|
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)) {
|
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ForbidExtensionFunctionTypeOnNonFunctionTypes)) {
|
||||||
reporter.reportOn(annotation.source, FirErrors.WRONG_EXTENSION_FUNCTION_TYPE, context)
|
reporter.reportOn(annotation.source, FirErrors.WRONG_EXTENSION_FUNCTION_TYPE, context)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -5,21 +5,20 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.renderer
|
package org.jetbrains.kotlin.fir.renderer
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import kotlin.contracts.ExperimentalContracts
|
|
||||||
import kotlin.contracts.contract
|
|
||||||
|
|
||||||
open class ConeTypeRenderer() {
|
open class ConeTypeRenderer {
|
||||||
|
|
||||||
lateinit var builder: StringBuilder
|
lateinit var builder: StringBuilder
|
||||||
lateinit var idRenderer: ConeIdRenderer
|
lateinit var idRenderer: ConeIdRenderer
|
||||||
|
|
||||||
open fun renderAsPossibleFunctionType(
|
open fun renderAsPossibleFunctionType(
|
||||||
type: ConeKotlinType, renderType: ConeTypeProjection.() -> Unit = { render() }
|
type: ConeKotlinType,
|
||||||
|
functionalClassKindExtractor: (ConeKotlinType) -> ConeFunctionalTypeKind?,
|
||||||
|
renderType: ConeTypeProjection.() -> Unit = { render() }
|
||||||
) {
|
) {
|
||||||
val kind = type.functionTypeKind
|
val kind = functionalClassKindExtractor(type)
|
||||||
if (!kind.withPrettyRender()) {
|
if (kind?.isReflectType != false) {
|
||||||
type.renderType()
|
type.renderType()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -27,8 +26,9 @@ open class ConeTypeRenderer() {
|
|||||||
if (type.isMarkedNullable) {
|
if (type.isMarkedNullable) {
|
||||||
builder.append("(")
|
builder.append("(")
|
||||||
}
|
}
|
||||||
if (kind == FunctionClassKind.SuspendFunction) {
|
kind.prefixForTypeRender?.let {
|
||||||
builder.append("suspend ")
|
builder.append(it)
|
||||||
|
builder.append(" ")
|
||||||
}
|
}
|
||||||
val typeArguments = type.typeArguments
|
val typeArguments = type.typeArguments
|
||||||
val isExtension = type.isExtensionFunctionType
|
val isExtension = type.isExtensionFunctionType
|
||||||
@@ -57,14 +57,6 @@ open class ConeTypeRenderer() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalContracts::class)
|
|
||||||
private fun FunctionClassKind?.withPrettyRender(): Boolean {
|
|
||||||
contract {
|
|
||||||
returns(true) implies (this@withPrettyRender != null)
|
|
||||||
}
|
|
||||||
return this != null && this != FunctionClassKind.KSuspendFunction && this != FunctionClassKind.KFunction
|
|
||||||
}
|
|
||||||
|
|
||||||
fun render(type: ConeKotlinType) {
|
fun render(type: ConeKotlinType) {
|
||||||
if (type !is ConeFlexibleType && type !is ConeDefinitelyNotNullType) {
|
if (type !is ConeFlexibleType && type !is ConeDefinitelyNotNullType) {
|
||||||
// We don't render attributes for flexible/definitely not null types here,
|
// We don't render attributes for flexible/definitely not null types here,
|
||||||
|
|||||||
+7
-2
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.renderer
|
package org.jetbrains.kotlin.fir.renderer
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeFunctionalTypeKind
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.ConeTypeProjection
|
import org.jetbrains.kotlin.fir.types.ConeTypeProjection
|
||||||
|
|
||||||
@@ -16,9 +17,13 @@ class ConeTypeRendererForDebugging() : ConeTypeRenderer() {
|
|||||||
idRenderer.builder = builder
|
idRenderer.builder = builder
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun renderAsPossibleFunctionType(type: ConeKotlinType, renderType: ConeTypeProjection.() -> Unit) {
|
override fun renderAsPossibleFunctionType(
|
||||||
|
type: ConeKotlinType,
|
||||||
|
functionalClassKindExtractor: (ConeKotlinType) -> ConeFunctionalTypeKind?,
|
||||||
|
renderType: ConeTypeProjection.() -> Unit
|
||||||
|
) {
|
||||||
builder.append("R|")
|
builder.append("R|")
|
||||||
super.renderAsPossibleFunctionType(type, renderType)
|
super.renderAsPossibleFunctionType(type, functionalClassKindExtractor, renderType)
|
||||||
builder.append("|")
|
builder.append("|")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.types
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.StandardNames
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [ConeFunctionalTypeKind] describes a family of various similar functional types (like kotlin.FunctionN)
|
||||||
|
* All types in the same family have corresponding shape of classId: [packageFqName].[classNamePrefix]N,
|
||||||
|
* where `N` is an arity of function
|
||||||
|
*
|
||||||
|
* Functional type kind may be either reflect type or non-reflect type
|
||||||
|
* Each non-reflect kind should have corresponding reflect kind and vice-versa (like `kotlin.FunctionN` and `kotlin.reflection.KFunctionN`)
|
||||||
|
*
|
||||||
|
* Classes for such functional types are synthetic and generated by compiler itself
|
||||||
|
* [annotationOnInvokeClassId] is a classId of annotation, which will be added to `invoke` function of generated
|
||||||
|
* functional interface. This argument is mandatory for non-standard functional kinds
|
||||||
|
*
|
||||||
|
* Assume we have `some.CustomFunctionN` and `some.KCustomFunctionN` families with [annotationOnInvokeClassId] = /some.Anno
|
||||||
|
* Classes for those kinds will look like this:
|
||||||
|
*
|
||||||
|
* interface CustomFunctionN<P1, P2, ..., PN, R> : kotlin.Function<R> {
|
||||||
|
* @some.Anno
|
||||||
|
* operator fun invoke(p1: P1, p2: P2, ..., pN: PN): R
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* interface KCustomFunctionN<P1, P2, ..., PN, R> : kotlin.reflect.KFunction<R>, some.CustomFunctionN<P1, P2, ..., PN, R> {
|
||||||
|
* @some.Anno
|
||||||
|
* override operator fun invoke(p1: P1, p2: P2, ..., pN: PN): R
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Note that if you provide some new functional type kind it's your responsibility to handle all references to it in backend
|
||||||
|
* with [IrGenerationExtension] implementation
|
||||||
|
*/
|
||||||
|
abstract class ConeFunctionalTypeKind internal constructor(
|
||||||
|
val packageFqName: FqName,
|
||||||
|
val classNamePrefix: String,
|
||||||
|
val isReflectType: Boolean,
|
||||||
|
val annotationOnInvokeClassId: ClassId?
|
||||||
|
) {
|
||||||
|
/*
|
||||||
|
* This constructor is needed to enforce not nullable [annotationOnInvokeClassId] for
|
||||||
|
* functional kinds provided by compiler plugins
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
packageFqName: FqName,
|
||||||
|
classNamePrefix: String,
|
||||||
|
annotationOnInvokeClassId: ClassId,
|
||||||
|
isReflectType: Boolean
|
||||||
|
) : this(packageFqName, classNamePrefix, isReflectType, annotationOnInvokeClassId)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Specifies how corresponding type will be rendered
|
||||||
|
* E.g. if `prefixForTypeRender = @Some` and type is `some.CustomFunction2<Int, String, Double>`,
|
||||||
|
* then type will be rendered as `@Some (Int, String) -> Double`
|
||||||
|
*/
|
||||||
|
open val prefixForTypeRender: String?
|
||||||
|
get() = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return corresponding non-reflect kind for reflect kind
|
||||||
|
* @return [this] if [isReflectType] is false
|
||||||
|
*
|
||||||
|
* Should be overridden for reflect kinds
|
||||||
|
*/
|
||||||
|
open fun nonReflectKind(): ConeFunctionalTypeKind {
|
||||||
|
return if (isReflectType) error("Should be overridden explicitly") else this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return corresponding reflect kind for non-reflect kind
|
||||||
|
* @return [this] if [isReflectType] is true
|
||||||
|
*
|
||||||
|
* Should be overridden for non reflect kinds
|
||||||
|
*/
|
||||||
|
open fun reflectKind(): ConeFunctionalTypeKind {
|
||||||
|
return if (isReflectType) this else error("Should be overridden explicitly")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun numberedClassName(arity: Int): Name = Name.identifier("$classNamePrefix$arity")
|
||||||
|
|
||||||
|
// ------------------------------------------- Builtin functional kinds -------------------------------------------
|
||||||
|
|
||||||
|
object Function : ConeFunctionalTypeKind(
|
||||||
|
StandardNames.BUILT_INS_PACKAGE_FQ_NAME,
|
||||||
|
"Function",
|
||||||
|
isReflectType = false,
|
||||||
|
annotationOnInvokeClassId = null
|
||||||
|
) {
|
||||||
|
override fun reflectKind(): ConeFunctionalTypeKind = KFunction
|
||||||
|
}
|
||||||
|
|
||||||
|
object SuspendFunction : ConeFunctionalTypeKind(
|
||||||
|
StandardNames.COROUTINES_PACKAGE_FQ_NAME,
|
||||||
|
"SuspendFunction",
|
||||||
|
isReflectType = false,
|
||||||
|
annotationOnInvokeClassId = null
|
||||||
|
) {
|
||||||
|
override val prefixForTypeRender: String
|
||||||
|
get() = "suspend"
|
||||||
|
|
||||||
|
override fun reflectKind(): ConeFunctionalTypeKind = KSuspendFunction
|
||||||
|
}
|
||||||
|
|
||||||
|
object KFunction : ConeFunctionalTypeKind(
|
||||||
|
StandardNames.KOTLIN_REFLECT_FQ_NAME,
|
||||||
|
"KFunction",
|
||||||
|
isReflectType = true,
|
||||||
|
annotationOnInvokeClassId = null
|
||||||
|
) {
|
||||||
|
override fun nonReflectKind(): ConeFunctionalTypeKind = Function
|
||||||
|
}
|
||||||
|
|
||||||
|
object KSuspendFunction : ConeFunctionalTypeKind(
|
||||||
|
StandardNames.KOTLIN_REFLECT_FQ_NAME,
|
||||||
|
"KSuspendFunction",
|
||||||
|
isReflectType = true,
|
||||||
|
annotationOnInvokeClassId = null
|
||||||
|
) {
|
||||||
|
override fun nonReflectKind(): ConeFunctionalTypeKind = SuspendFunction
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,8 +5,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.types
|
package org.jetbrains.kotlin.fir.types
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
import org.jetbrains.kotlin.fir.renderer.ConeIdRendererForDebugging
|
||||||
import org.jetbrains.kotlin.fir.renderer.*
|
import org.jetbrains.kotlin.fir.renderer.ConeIdShortRenderer
|
||||||
|
import org.jetbrains.kotlin.fir.renderer.ConeTypeRendererForDebugging
|
||||||
|
import org.jetbrains.kotlin.fir.renderer.ConeTypeRendererWithJavaFlexibleTypes
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
@@ -111,14 +113,6 @@ fun ConeClassLikeType.replaceArgumentsWithStarProjections(): ConeClassLikeType {
|
|||||||
return withArguments(newArguments)
|
return withArguments(newArguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
val ConeKotlinType?.functionTypeKind: FunctionClassKind?
|
|
||||||
get() {
|
|
||||||
val classId = (this as? ConeClassLikeType)?.lookupTag?.classId ?: return null
|
|
||||||
return FunctionClassKind.getFunctionalClassKind(
|
|
||||||
classId.shortClassName.asString(), classId.packageFqName
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ConeKotlinType.renderForDebugging(): String {
|
fun ConeKotlinType.renderForDebugging(): String {
|
||||||
val builder = StringBuilder()
|
val builder = StringBuilder()
|
||||||
ConeTypeRendererForDebugging(builder).render(this)
|
ConeTypeRendererForDebugging(builder).render(this)
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirIntersectionOverrideStorage
|
|||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirSubstitutionOverrideStorage
|
import org.jetbrains.kotlin.fir.scopes.impl.FirSubstitutionOverrideStorage
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirLazyDeclarationResolver
|
import org.jetbrains.kotlin.fir.symbols.FirLazyDeclarationResolver
|
||||||
import org.jetbrains.kotlin.fir.types.FirCorrespondingSupertypesCache
|
import org.jetbrains.kotlin.fir.types.FirCorrespondingSupertypesCache
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirFunctionalTypeKindService
|
||||||
import org.jetbrains.kotlin.fir.types.TypeComponents
|
import org.jetbrains.kotlin.fir.types.TypeComponents
|
||||||
import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
|
import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
|
||||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||||
@@ -71,6 +72,9 @@ fun FirSession.registerCommonComponents(languageVersionSettings: LanguageVersion
|
|||||||
register(FirSamConstructorStorage::class, FirSamConstructorStorage(this))
|
register(FirSamConstructorStorage::class, FirSamConstructorStorage(this))
|
||||||
register(FirOverrideService::class, FirOverrideService(this))
|
register(FirOverrideService::class, FirOverrideService(this))
|
||||||
register(FirDynamicMembersStorage::class, FirDynamicMembersStorage(this))
|
register(FirDynamicMembersStorage::class, FirDynamicMembersStorage(this))
|
||||||
|
|
||||||
|
// TODO: replace with proper implementation
|
||||||
|
register(FirFunctionalTypeKindService::class, FirFunctionalTypeKindService.Default)
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(SessionConfiguration::class)
|
@OptIn(SessionConfiguration::class)
|
||||||
|
|||||||
+36
-52
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.providers.impl
|
package org.jetbrains.kotlin.fir.resolve.providers.impl
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.fir.FirModuleData
|
import org.jetbrains.kotlin.fir.FirModuleData
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
@@ -25,16 +24,15 @@ import org.jetbrains.kotlin.fir.deserialization.FirBuiltinAnnotationDeserializer
|
|||||||
import org.jetbrains.kotlin.fir.deserialization.FirConstDeserializer
|
import org.jetbrains.kotlin.fir.deserialization.FirConstDeserializer
|
||||||
import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext
|
import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext
|
||||||
import org.jetbrains.kotlin.fir.deserialization.deserializeClassToSymbol
|
import org.jetbrains.kotlin.fir.deserialization.deserializeClassToSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotation
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyAnnotationArgumentMapping
|
||||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
|
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
|
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
|
||||||
import org.jetbrains.kotlin.fir.types.constructClassType
|
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||||
import org.jetbrains.kotlin.fir.types.toLookupTag
|
|
||||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion
|
import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion
|
||||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
|
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
|
||||||
@@ -53,7 +51,7 @@ open class FirBuiltinSymbolProvider(
|
|||||||
val kotlinScopeProvider: FirKotlinScopeProvider
|
val kotlinScopeProvider: FirKotlinScopeProvider
|
||||||
) : FirSymbolProvider(session) {
|
) : FirSymbolProvider(session) {
|
||||||
private val allPackageFragments = loadBuiltIns().groupBy { it.fqName }
|
private val allPackageFragments = loadBuiltIns().groupBy { it.fqName }
|
||||||
private val syntheticFunctionalInterfaceCache = SyntheticFunctionalInterfaceCache(moduleData, kotlinScopeProvider)
|
private val syntheticFunctionalInterfaceCache = SyntheticFunctionalInterfaceCache(session, moduleData, kotlinScopeProvider)
|
||||||
|
|
||||||
private fun loadBuiltIns(): List<BuiltInsPackageFragment> {
|
private fun loadBuiltIns(): List<BuiltInsPackageFragment> {
|
||||||
val classLoader = this::class.java.classLoader
|
val classLoader = this::class.java.classLoader
|
||||||
@@ -201,7 +199,11 @@ private data class BinaryVersionAndPackageFragment(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SyntheticFunctionalInterfaceCache(private val moduleData: FirModuleData, private val kotlinScopeProvider: FirKotlinScopeProvider) {
|
private class SyntheticFunctionalInterfaceCache(
|
||||||
|
private val session: FirSession,
|
||||||
|
private val moduleData: FirModuleData,
|
||||||
|
private val kotlinScopeProvider: FirKotlinScopeProvider
|
||||||
|
) {
|
||||||
private val syntheticFunctionalInterfaceCache =
|
private val syntheticFunctionalInterfaceCache =
|
||||||
moduleData.session.firCachesFactory.createCache(::createSyntheticFunctionalInterface)
|
moduleData.session.firCachesFactory.createCache(::createSyntheticFunctionalInterface)
|
||||||
|
|
||||||
@@ -212,7 +214,7 @@ private class SyntheticFunctionalInterfaceCache(private val moduleData: FirModul
|
|||||||
private fun createSyntheticFunctionalInterface(classId: ClassId): FirRegularClassSymbol? {
|
private fun createSyntheticFunctionalInterface(classId: ClassId): FirRegularClassSymbol? {
|
||||||
return with(classId) {
|
return with(classId) {
|
||||||
val className = relativeClassName.asString()
|
val className = relativeClassName.asString()
|
||||||
val kind = FunctionClassKind.byClassNamePrefix(packageFqName, className) ?: return@with null
|
val kind = session.functionalTypeService.getKindByClassNamePrefix(packageFqName, className) ?: return null
|
||||||
val prefix = kind.classNamePrefix
|
val prefix = kind.classNamePrefix
|
||||||
val arity = className.substring(prefix.length).toIntOrNull() ?: return null
|
val arity = className.substring(prefix.length).toIntOrNull() ?: return null
|
||||||
FirRegularClassSymbol(classId).apply symbol@{
|
FirRegularClassSymbol(classId).apply symbol@{
|
||||||
@@ -279,55 +281,30 @@ private class SyntheticFunctionalInterfaceCache(private val moduleData: FirModul
|
|||||||
isTailRec = false
|
isTailRec = false
|
||||||
isExternal = false
|
isExternal = false
|
||||||
isSuspend =
|
isSuspend =
|
||||||
kind == FunctionClassKind.SuspendFunction ||
|
kind == ConeFunctionalTypeKind.SuspendFunction ||
|
||||||
kind == FunctionClassKind.KSuspendFunction
|
kind == ConeFunctionalTypeKind.KSuspendFunction
|
||||||
}
|
}
|
||||||
val typeArguments = typeParameters.map {
|
val typeArguments = typeParameters.map {
|
||||||
buildResolvedTypeRef {
|
ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false).toFirResolvedTypeRef()
|
||||||
type = ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createSuperType(
|
fun createSuperType(kind: ConeFunctionalTypeKind): FirResolvedTypeRef {
|
||||||
kind: FunctionClassKind,
|
return kind.classId(arity).toLookupTag()
|
||||||
): FirResolvedTypeRef {
|
.constructClassType(typeArguments.map { it.type }.toTypedArray(), isNullable = false)
|
||||||
return buildResolvedTypeRef {
|
.toFirResolvedTypeRef()
|
||||||
type = kind.classId(arity).toLookupTag()
|
|
||||||
.constructClassType(typeArguments.map { it.type }.toTypedArray(), isNullable = false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
superTypeRefs += when (kind) {
|
if (kind.isReflectType) {
|
||||||
FunctionClassKind.Function -> listOf(
|
superTypeRefs += StandardClassIds.KFunction.toLookupTag()
|
||||||
buildResolvedTypeRef {
|
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
|
||||||
type = StandardClassIds.Function.toLookupTag()
|
.toFirResolvedTypeRef()
|
||||||
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
|
superTypeRefs += createSuperType(kind.nonReflectKind())
|
||||||
}
|
} else {
|
||||||
)
|
superTypeRefs += StandardClassIds.Function.toLookupTag()
|
||||||
|
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
|
||||||
FunctionClassKind.SuspendFunction -> listOf(
|
.toFirResolvedTypeRef()
|
||||||
buildResolvedTypeRef {
|
|
||||||
type = StandardClassIds.Function.toLookupTag()
|
|
||||||
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
FunctionClassKind.KFunction -> listOf(
|
|
||||||
buildResolvedTypeRef {
|
|
||||||
type = StandardClassIds.KFunction.toLookupTag()
|
|
||||||
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
|
|
||||||
},
|
|
||||||
createSuperType(FunctionClassKind.Function)
|
|
||||||
)
|
|
||||||
|
|
||||||
FunctionClassKind.KSuspendFunction -> listOf(
|
|
||||||
buildResolvedTypeRef {
|
|
||||||
type = StandardClassIds.KFunction.toLookupTag()
|
|
||||||
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
|
|
||||||
},
|
|
||||||
createSuperType(FunctionClassKind.SuspendFunction)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addDeclaration(
|
addDeclaration(
|
||||||
buildSimpleFunction {
|
buildSimpleFunction {
|
||||||
moduleData = this@SyntheticFunctionalInterfaceCache.moduleData
|
moduleData = this@SyntheticFunctionalInterfaceCache.moduleData
|
||||||
@@ -357,6 +334,14 @@ private class SyntheticFunctionalInterfaceCache(private val moduleData: FirModul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dispatchReceiverType = classId.defaultType(this@klass.typeParameters.map { it.symbol })
|
dispatchReceiverType = classId.defaultType(this@klass.typeParameters.map { it.symbol })
|
||||||
|
kind.annotationOnInvokeClassId?.let { annotationClassId ->
|
||||||
|
annotations += buildAnnotation {
|
||||||
|
annotationTypeRef = annotationClassId
|
||||||
|
.constructClassLikeType(emptyArray(), isNullable = false)
|
||||||
|
.toFirResolvedTypeRef()
|
||||||
|
argumentMapping = FirEmptyAnnotationArgumentMapping
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -364,6 +349,5 @@ private class SyntheticFunctionalInterfaceCache(private val moduleData: FirModul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ConeFunctionalTypeKind.classId(arity: Int) = ClassId(packageFqName, numberedClassName(arity))
|
||||||
private fun FunctionClassKind.classId(arity: Int) = ClassId(packageFqName, numberedClassName(arity))
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.serialization
|
package org.jetbrains.kotlin.fir.serialization
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.StandardNames
|
import org.jetbrains.kotlin.builtins.StandardNames
|
||||||
|
import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKind
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
@@ -681,7 +682,7 @@ class FirElementSerializer private constructor(
|
|||||||
return lowerBound
|
return lowerBound
|
||||||
}
|
}
|
||||||
is ConeClassLikeType -> {
|
is ConeClassLikeType -> {
|
||||||
if (type.isSuspendFunctionType(session)) {
|
if (type.functionalTypeKind(session) == FunctionalTypeKind.SuspendFunction) {
|
||||||
val runtimeFunctionType = type.suspendFunctionTypeToFunctionTypeWithContinuation(
|
val runtimeFunctionType = type.suspendFunctionTypeToFunctionTypeWithContinuation(
|
||||||
session, StandardClassIds.Continuation
|
session, StandardClassIds.Continuation
|
||||||
)
|
)
|
||||||
|
|||||||
+24
-2
@@ -5,11 +5,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.serialization
|
package org.jetbrains.kotlin.fir.serialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
|
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.fir.types.ConeErrorType
|
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||||
import org.jetbrains.kotlin.fir.types.typeContext
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeApproximator
|
import org.jetbrains.kotlin.types.AbstractTypeApproximator
|
||||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||||
|
|
||||||
@@ -21,3 +24,22 @@ class TypeApproximatorForMetadataSerializer(session: FirSession) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ConeKotlinType.suspendFunctionTypeToFunctionTypeWithContinuation(session: FirSession, continuationClassId: ClassId): ConeClassLikeType {
|
||||||
|
require(this.isSuspendFunctionType(session))
|
||||||
|
val kind =
|
||||||
|
if (isReflectFunctionalType(session)) FunctionClassKind.KFunction
|
||||||
|
else FunctionClassKind.Function
|
||||||
|
val fullyExpandedType = type.fullyExpandedType(session)
|
||||||
|
val typeArguments = fullyExpandedType.typeArguments
|
||||||
|
val functionalTypeId = ClassId(kind.packageFqName, kind.numberedClassName(typeArguments.size))
|
||||||
|
val lastTypeArgument = typeArguments.last()
|
||||||
|
return ConeClassLikeTypeImpl(
|
||||||
|
functionalTypeId.toLookupTag(),
|
||||||
|
typeArguments = (typeArguments.dropLast(1) + continuationClassId.toLookupTag().constructClassType(
|
||||||
|
arrayOf(lastTypeArgument),
|
||||||
|
isNullable = false
|
||||||
|
) + lastTypeArgument).toTypedArray(),
|
||||||
|
isNullable = fullyExpandedType.isNullable,
|
||||||
|
attributes = fullyExpandedType.attributes
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
+2
-2
@@ -233,8 +233,8 @@ class FirJvmSerializerExtension(
|
|||||||
private fun FirFunction.needsInlineParameterNullCheckRequirement(): Boolean =
|
private fun FirFunction.needsInlineParameterNullCheckRequirement(): Boolean =
|
||||||
this is FirSimpleFunction && isInline && !isSuspend && !isParamAssertionsDisabled &&
|
this is FirSimpleFunction && isInline && !isSuspend && !isParamAssertionsDisabled &&
|
||||||
!Visibilities.isPrivate(visibility) &&
|
!Visibilities.isPrivate(visibility) &&
|
||||||
(valueParameters.any { it.returnTypeRef.coneType.isBuiltinFunctionalType(session) } ||
|
(valueParameters.any { it.returnTypeRef.coneType.isSomeFunctionalType(session) } ||
|
||||||
receiverParameter?.typeRef?.coneType?.isBuiltinFunctionalType(session) == true)
|
receiverParameter?.typeRef?.coneType?.isSomeFunctionalType(session) == true)
|
||||||
|
|
||||||
override fun serializeProperty(
|
override fun serializeProperty(
|
||||||
property: FirProperty,
|
property: FirProperty,
|
||||||
|
|||||||
+3
-3
@@ -172,8 +172,8 @@ class FirJvmTypeMapper(val session: FirSession) : FirSessionComponent {
|
|||||||
val parameters = classifier?.typeParameters.orEmpty().map { it.symbol }
|
val parameters = classifier?.typeParameters.orEmpty().map { it.symbol }
|
||||||
val arguments = type.arguments
|
val arguments = type.arguments
|
||||||
|
|
||||||
if ((defaultType.isFunctionalType(session) && arguments.size > BuiltInFunctionArity.BIG_ARITY)
|
if ((defaultType.isSimpleFunctionType(session) && arguments.size > BuiltInFunctionArity.BIG_ARITY)
|
||||||
|| defaultType.isKFunctionType(session)
|
|| defaultType.isReflectFunctionalType(session)
|
||||||
) {
|
) {
|
||||||
writeGenericArguments(sw, listOf(arguments.last()), listOf(parameters.last()), mode)
|
writeGenericArguments(sw, listOf(arguments.last()), listOf(parameters.last()), mode)
|
||||||
return
|
return
|
||||||
@@ -264,7 +264,7 @@ class ConeTypeSystemCommonBackendContextForTypeMapping(
|
|||||||
|
|
||||||
override fun SimpleTypeMarker.isSuspendFunction(): Boolean {
|
override fun SimpleTypeMarker.isSuspendFunction(): Boolean {
|
||||||
require(this is ConeSimpleKotlinType)
|
require(this is ConeSimpleKotlinType)
|
||||||
return isSuspendOrKSuspendFunctionType(session)
|
return isSuspendFunctionType(session)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun SimpleTypeMarker.isKClass(): Boolean {
|
override fun SimpleTypeMarker.isKClass(): Boolean {
|
||||||
|
|||||||
+1
-1
@@ -538,7 +538,7 @@ class Fir2IrDeclarationStorage(
|
|||||||
?: if (isLambda) SpecialNames.ANONYMOUS else Name.special("<no name provided>")
|
?: if (isLambda) SpecialNames.ANONYMOUS else Name.special("<no name provided>")
|
||||||
val visibility = simpleFunction?.visibility ?: Visibilities.Local
|
val visibility = simpleFunction?.visibility ?: Visibilities.Local
|
||||||
val isSuspend =
|
val isSuspend =
|
||||||
if (isLambda) ((function as FirAnonymousFunction).typeRef as? FirResolvedTypeRef)?.type?.isSuspendOrKSuspendFunctionType(session) == true
|
if (isLambda) ((function as FirAnonymousFunction).typeRef as? FirResolvedTypeRef)?.type?.isSuspendFunctionType(session) == true
|
||||||
else simpleFunction?.isSuspend == true
|
else simpleFunction?.isSuspend == true
|
||||||
val created = function.convertWithOffsets { startOffset, endOffset ->
|
val created = function.convertWithOffsets { startOffset, endOffset ->
|
||||||
val result = declareIrSimpleFunction(signature, simpleFunction?.containerSource) { symbol ->
|
val result = declareIrSimpleFunction(signature, simpleFunction?.containerSource) { symbol ->
|
||||||
|
|||||||
+6
-6
@@ -134,7 +134,7 @@ internal class AdapterGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun ConeKotlinType.kFunctionTypeToFunctionType(): IrSimpleType =
|
internal fun ConeKotlinType.kFunctionTypeToFunctionType(): IrSimpleType =
|
||||||
kFunctionTypeToFunctionType(session).toIrType() as IrSimpleType
|
reflectFunctionalTypeToNonReflectFunctionalType(session).toIrType() as IrSimpleType
|
||||||
|
|
||||||
internal fun generateAdaptedCallableReference(
|
internal fun generateAdaptedCallableReference(
|
||||||
callableReferenceAccess: FirCallableReferenceAccess,
|
callableReferenceAccess: FirCallableReferenceAccess,
|
||||||
@@ -479,7 +479,7 @@ internal class AdapterGenerator(
|
|||||||
}
|
}
|
||||||
// If the expected type is a built-in functional type, we don't need SAM conversion.
|
// If the expected type is a built-in functional type, we don't need SAM conversion.
|
||||||
val expectedType = argument.getExpectedType(parameter)
|
val expectedType = argument.getExpectedType(parameter)
|
||||||
if (expectedType is ConeTypeParameterType || expectedType.isBuiltinFunctionalType(session)) {
|
if (expectedType is ConeTypeParameterType || expectedType.isSomeFunctionalType(session)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// On the other hand, the actual type should be either a functional type or a subtype of a class that has a contributed `invoke`.
|
// On the other hand, the actual type should be either a functional type or a subtype of a class that has a contributed `invoke`.
|
||||||
@@ -514,10 +514,10 @@ internal class AdapterGenerator(
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
// Expect the expected type to be a suspend functional type.
|
// Expect the expected type to be a suspend functional type.
|
||||||
if (!parameterType.isSuspendOrKSuspendFunctionType(session)) {
|
if (!parameterType.isSuspendFunctionType(session)) {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
val expectedFunctionalType = parameterType.suspendFunctionTypeToFunctionType(session)
|
val expectedFunctionalType = parameterType.customFunctionalTypeToSimpleFunctionalType(session)
|
||||||
if (this is IrVararg) {
|
if (this is IrVararg) {
|
||||||
// element-wise conversion if and only if we can build 1-to-1 mapping for elements.
|
// element-wise conversion if and only if we can build 1-to-1 mapping for elements.
|
||||||
return applyConversionOnVararg(argument) { firVarargArgument ->
|
return applyConversionOnVararg(argument) { firVarargArgument ->
|
||||||
@@ -546,9 +546,9 @@ internal class AdapterGenerator(
|
|||||||
argument: FirExpression
|
argument: FirExpression
|
||||||
): IrSimpleFunctionSymbol? {
|
): IrSimpleFunctionSymbol? {
|
||||||
val argumentType = argument.typeRef.coneType
|
val argumentType = argument.typeRef.coneType
|
||||||
val argumentTypeWithInvoke = argumentType.findSubtypeOfNonSuspendFunctionalType(session, expectedFunctionalType) ?: return null
|
val argumentTypeWithInvoke = argumentType.findSubtypeOfSimpleFunctionalType(session, expectedFunctionalType) ?: return null
|
||||||
|
|
||||||
return if (argumentTypeWithInvoke.isBuiltinFunctionalType(session)) {
|
return if (argumentTypeWithInvoke.isSomeFunctionalType(session)) {
|
||||||
(argumentTypeWithInvoke as? ConeClassLikeType)?.findBaseInvokeSymbol(session, scopeSession)
|
(argumentTypeWithInvoke as? ConeClassLikeType)?.findBaseInvokeSymbol(session, scopeSession)
|
||||||
} else {
|
} else {
|
||||||
argumentTypeWithInvoke.findContributedInvokeSymbol(
|
argumentTypeWithInvoke.findContributedInvokeSymbol(
|
||||||
|
|||||||
+1
-1
@@ -188,7 +188,7 @@ class CallAndReferenceGenerator(
|
|||||||
// This would cause ClassCastException in case of usual type approximation,
|
// This would cause ClassCastException in case of usual type approximation,
|
||||||
// because '{ X1 & ... & Xm }' would be approximated to 'Nothing'.
|
// because '{ X1 & ... & Xm }' would be approximated to 'Nothing'.
|
||||||
// JVM_OLD just relies on type mapping for generic argument types in such case.
|
// JVM_OLD just relies on type mapping for generic argument types in such case.
|
||||||
if (!kotlinType.isKFunctionType(session))
|
if (!kotlinType.isReflectFunctionalType(session))
|
||||||
return kotlinType
|
return kotlinType
|
||||||
if (kotlinType !is ConeSimpleKotlinType)
|
if (kotlinType !is ConeSimpleKotlinType)
|
||||||
return kotlinType
|
return kotlinType
|
||||||
|
|||||||
+2
-2
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.providers.impl
|
package org.jetbrains.kotlin.fir.resolve.providers.impl
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.NoMutableState
|
import org.jetbrains.kotlin.fir.NoMutableState
|
||||||
import org.jetbrains.kotlin.fir.caches.FirCache
|
import org.jetbrains.kotlin.fir.caches.FirCache
|
||||||
@@ -19,6 +18,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
|||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.functionalTypeService
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -116,7 +116,7 @@ class FirCachingCompositeSymbolProvider(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun isNameForFunctionClass(classId: ClassId): Boolean {
|
private fun isNameForFunctionClass(classId: ClassId): Boolean {
|
||||||
return FunctionClassKind.byClassNamePrefix(classId.packageFqName, classId.shortClassName.asString()) != null
|
return session.functionalTypeService.getKindByClassNamePrefix(classId.packageFqName, classId.shortClassName.asString()) != null
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(FirSymbolProviderInternals::class)
|
@OptIn(FirSymbolProviderInternals::class)
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
|||||||
): SimpleTypeMarker {
|
): SimpleTypeMarker {
|
||||||
val attributesList = attributes?.filterIsInstanceTo<ConeAttribute<*>, MutableList<ConeAttribute<*>>>(mutableListOf())
|
val attributesList = attributes?.filterIsInstanceTo<ConeAttribute<*>, MutableList<ConeAttribute<*>>>(mutableListOf())
|
||||||
val coneAttributes: ConeAttributes = if (isExtensionFunction) {
|
val coneAttributes: ConeAttributes = if (isExtensionFunction) {
|
||||||
require(constructor is ConeClassLikeLookupTag && constructor.isBuiltinFunctionalType())
|
require(constructor is ConeClassLikeLookupTag && constructor.isSomeFunctionalType(session))
|
||||||
// We don't want to create new instance of ConeAttributes which
|
// We don't want to create new instance of ConeAttributes which
|
||||||
// contains only CompilerConeAttributes.ExtensionFunctionType
|
// contains only CompilerConeAttributes.ExtensionFunctionType
|
||||||
// to avoid memory consumption
|
// to avoid memory consumption
|
||||||
@@ -226,7 +226,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
|||||||
override fun KotlinTypeMarker.isBuiltinFunctionalTypeOrSubtype(): Boolean {
|
override fun KotlinTypeMarker.isBuiltinFunctionalTypeOrSubtype(): Boolean {
|
||||||
require(this is ConeKotlinType)
|
require(this is ConeKotlinType)
|
||||||
return this.isTypeOrSubtypeOf {
|
return this.isTypeOrSubtypeOf {
|
||||||
(it.lowerBoundIfFlexible() as ConeKotlinType).isBuiltinFunctionalType(session)
|
(it.lowerBoundIfFlexible() as ConeKotlinType).isSomeFunctionalType(session)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,7 +463,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
|||||||
|
|
||||||
override fun KotlinTypeMarker.isFunctionOrKFunctionWithAnySuspendability(): Boolean {
|
override fun KotlinTypeMarker.isFunctionOrKFunctionWithAnySuspendability(): Boolean {
|
||||||
require(this is ConeKotlinType)
|
require(this is ConeKotlinType)
|
||||||
return this.isBuiltinFunctionalType(session)
|
return this.isSomeFunctionalType(session)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ConeKotlinType.isTypeOrSubtypeOf(predicate: (ConeKotlinType) -> Boolean): Boolean {
|
private fun ConeKotlinType.isTypeOrSubtypeOf(predicate: (ConeKotlinType) -> Boolean): Boolean {
|
||||||
@@ -519,13 +519,13 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
|||||||
|
|
||||||
return fullyExpandedType(session).let {
|
return fullyExpandedType(session).let {
|
||||||
val simpleType = it.lowerBoundIfFlexible()
|
val simpleType = it.lowerBoundIfFlexible()
|
||||||
if ((simpleType as ConeKotlinType).isBuiltinFunctionalType(session))
|
if ((simpleType as ConeKotlinType).isSomeFunctionalType(session))
|
||||||
this
|
this
|
||||||
else {
|
else {
|
||||||
var functionalSupertype: KotlinTypeMarker? = null
|
var functionalSupertype: KotlinTypeMarker? = null
|
||||||
simpleType.anySuperTypeConstructor { type ->
|
simpleType.anySuperTypeConstructor { type ->
|
||||||
simpleType.fastCorrespondingSupertypes(type.typeConstructor())?.any { superType ->
|
simpleType.fastCorrespondingSupertypes(type.typeConstructor())?.any { superType ->
|
||||||
val isFunctional = (superType as ConeKotlinType).isBuiltinFunctionalType(session)
|
val isFunctional = (superType as ConeKotlinType).isSomeFunctionalType(session)
|
||||||
if (isFunctional)
|
if (isFunctional)
|
||||||
functionalSupertype = superType
|
functionalSupertype = superType
|
||||||
isFunctional
|
isFunctional
|
||||||
|
|||||||
@@ -0,0 +1,248 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.types
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||||
|
import org.jetbrains.kotlin.fir.originalForSubstitutionOverride
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.scope
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.runUnless
|
||||||
|
|
||||||
|
// ---------------------------------------------- is type is a functional type ----------------------------------------------
|
||||||
|
|
||||||
|
fun ConeKotlinType.functionalTypeKind(session: FirSession): ConeFunctionalTypeKind? {
|
||||||
|
if (this !is ConeClassLikeType) return null
|
||||||
|
return fullyExpandedType(session).lookupTag.functionalTypeKind(session)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ConeClassLikeLookupTag.functionalTypeKind(session: FirSession): ConeFunctionalTypeKind? {
|
||||||
|
val classId = classId
|
||||||
|
return session.functionalTypeService.getKindByClassNamePrefix(classId.packageFqName, classId.shortClassName.asString())
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun ConeKotlinType.isFunctionalTypeWithPredicate(
|
||||||
|
session: FirSession,
|
||||||
|
errorOnNotFunctionalType: Boolean = false,
|
||||||
|
predicate: (ConeFunctionalTypeKind) -> Boolean
|
||||||
|
): Boolean {
|
||||||
|
val kind = functionalTypeKind(session)
|
||||||
|
?: if (errorOnNotFunctionalType) error("$this is not a functional type") else return false
|
||||||
|
return predicate(kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function
|
||||||
|
fun ConeKotlinType.isSimpleFunctionType(session: FirSession): Boolean {
|
||||||
|
return isFunctionalTypeWithPredicate(session) { it == ConeFunctionalTypeKind.Function }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function, SuspendFunction, [Custom]Function
|
||||||
|
fun ConeKotlinType.isNonReflectFunctionalType(session: FirSession): Boolean {
|
||||||
|
return isFunctionalTypeWithPredicate(session) { !it.isReflectType }
|
||||||
|
}
|
||||||
|
|
||||||
|
// SuspendFunction, KSuspendFunction
|
||||||
|
fun ConeKotlinType.isSuspendFunctionType(session: FirSession): Boolean {
|
||||||
|
return isFunctionalTypeWithPredicate(session) {
|
||||||
|
it == ConeFunctionalTypeKind.SuspendFunction || it == ConeFunctionalTypeKind.KSuspendFunction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// KFunction, KSuspendFunction, K[Custom]Function
|
||||||
|
fun ConeKotlinType.isReflectFunctionalType(session: FirSession): Boolean {
|
||||||
|
return isFunctionalTypeWithPredicate(session) { it.isReflectType }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function, SuspendFunction, [Custom]Function, KFunction, KSuspendFunction, K[Custom]Function
|
||||||
|
fun ConeKotlinType.isSomeFunctionalType(session: FirSession): Boolean {
|
||||||
|
return functionalTypeKind(session) != null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function, SuspendFunction, [Custom]Function, KFunction, KSuspendFunction, K[Custom]Function
|
||||||
|
fun ConeClassLikeLookupTag.isSomeFunctionalType(session: FirSession): Boolean {
|
||||||
|
return functionalTypeKind(session) != null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function, KFunction
|
||||||
|
private fun ConeKotlinType.isSimpleFunctionalType(session: FirSession, errorOnNotFunctionalType: Boolean): Boolean {
|
||||||
|
return isFunctionalTypeWithPredicate(session, errorOnNotFunctionalType) {
|
||||||
|
it == ConeFunctionalTypeKind.Function || it == ConeFunctionalTypeKind.KFunction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SuspendFunction, [Custom]Function, KSuspendFunction, K[Custom]Function
|
||||||
|
private fun ConeKotlinType.isNotSimpleFunctionalType(session: FirSession): Boolean {
|
||||||
|
return !isSimpleFunctionalType(session, errorOnNotFunctionalType = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------- functional type conversions ----------------------------------------------
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SuspendFunction/[Custom]Function -> Function
|
||||||
|
* KSuspendFunction/K[Custom]Function -> KFunction
|
||||||
|
*/
|
||||||
|
fun ConeKotlinType.customFunctionalTypeToSimpleFunctionalType(session: FirSession): ConeClassLikeType {
|
||||||
|
val kind = functionalTypeKind(session)
|
||||||
|
require(kind != null && kind != ConeFunctionalTypeKind.Function && kind != ConeFunctionalTypeKind.KFunction)
|
||||||
|
val newKind = if (kind.isReflectType) {
|
||||||
|
ConeFunctionalTypeKind.KFunction
|
||||||
|
} else {
|
||||||
|
ConeFunctionalTypeKind.Function
|
||||||
|
}
|
||||||
|
return createFunctionalTypeWithNewKind(newKind)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* KFunction -> Function
|
||||||
|
* KSuspendFunction -> SuspendFunction
|
||||||
|
* K[Custom]Function -> [Custom]Function
|
||||||
|
*/
|
||||||
|
fun ConeKotlinType.reflectFunctionalTypeToNonReflectFunctionalType(session: FirSession): ConeClassLikeType {
|
||||||
|
val kind = functionalTypeKind(session)
|
||||||
|
require(kind != null && kind.isReflectType)
|
||||||
|
return createFunctionalTypeWithNewKind(kind.nonReflectKind())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ConeKotlinType.createFunctionalTypeWithNewKind(kind: ConeFunctionalTypeKind): ConeClassLikeType {
|
||||||
|
val functionalTypeId = ClassId(kind.packageFqName, kind.numberedClassName(typeArguments.size - 1))
|
||||||
|
return functionalTypeId.toLookupTag().constructClassType(typeArguments, isNullable = false, attributes = attributes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------- functional type subtyping ----------------------------------------------
|
||||||
|
|
||||||
|
// expectedFunctionalType is kotlin.FunctionN or kotlin.reflect.KFunctionN
|
||||||
|
fun ConeKotlinType.findSubtypeOfSimpleFunctionalType(session: FirSession, expectedFunctionalType: ConeClassLikeType): ConeKotlinType? {
|
||||||
|
require(expectedFunctionalType.isSimpleFunctionalType(session, errorOnNotFunctionalType = true))
|
||||||
|
return findSubtypeOfSimpleFunctionalTypeImpl(session, expectedFunctionalType)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ConeKotlinType.findSubtypeOfSimpleFunctionalTypeImpl(
|
||||||
|
session: FirSession,
|
||||||
|
expectedFunctionalType: ConeClassLikeType
|
||||||
|
): ConeKotlinType? {
|
||||||
|
return when (this) {
|
||||||
|
is ConeClassLikeType -> {
|
||||||
|
// Expect the argument type is a simple functional type.
|
||||||
|
when {
|
||||||
|
isNotSimpleFunctionalType(session) -> null
|
||||||
|
isSubtypeOfFunctionalType(session, expectedFunctionalType) -> this
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is ConeIntersectionType -> {
|
||||||
|
runUnless(intersectedTypes.any { it.isNotSimpleFunctionalType(session) }) {
|
||||||
|
intersectedTypes.find { it.findSubtypeOfSimpleFunctionalTypeImpl(session, expectedFunctionalType) != null }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is ConeTypeParameterType -> {
|
||||||
|
val bounds = lookupTag.typeParameterSymbol.resolvedBounds.map { it.coneType }
|
||||||
|
runUnless(bounds.any { it.isNotSimpleFunctionalType(session) }) {
|
||||||
|
bounds.find { it.findSubtypeOfSimpleFunctionalTypeImpl(session, expectedFunctionalType) != null }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ConeKotlinType.isSubtypeOfFunctionalType(session: FirSession, expectedFunctionalType: ConeClassLikeType): Boolean {
|
||||||
|
return AbstractTypeChecker.isSubtypeOf(session.typeContext, this, expectedFunctionalType.replaceArgumentsWithStarProjections())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------- functional type scope utils ----------------------------------------------
|
||||||
|
|
||||||
|
fun ConeClassLikeType.findBaseInvokeSymbol(session: FirSession, scopeSession: ScopeSession): FirNamedFunctionSymbol? {
|
||||||
|
require(this.isSomeFunctionalType(session))
|
||||||
|
val functionN = (lookupTag.toSymbol(session)?.fir as? FirClass) ?: return null
|
||||||
|
var baseInvokeSymbol: FirNamedFunctionSymbol? = null
|
||||||
|
functionN.unsubstitutedScope(
|
||||||
|
session,
|
||||||
|
scopeSession,
|
||||||
|
withForcedTypeCalculator = false
|
||||||
|
).processFunctionsByName(OperatorNameConventions.INVOKE) { functionSymbol ->
|
||||||
|
baseInvokeSymbol = functionSymbol
|
||||||
|
return@processFunctionsByName
|
||||||
|
}
|
||||||
|
return baseInvokeSymbol
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ConeKotlinType.findContributedInvokeSymbol(
|
||||||
|
session: FirSession,
|
||||||
|
scopeSession: ScopeSession,
|
||||||
|
expectedFunctionalType: ConeClassLikeType,
|
||||||
|
shouldCalculateReturnTypesOfFakeOverrides: Boolean
|
||||||
|
): FirFunctionSymbol<*>? {
|
||||||
|
val baseInvokeSymbol = expectedFunctionalType.findBaseInvokeSymbol(session, scopeSession) ?: return null
|
||||||
|
|
||||||
|
val fakeOverrideTypeCalculator = if (shouldCalculateReturnTypesOfFakeOverrides) {
|
||||||
|
FakeOverrideTypeCalculator.Forced
|
||||||
|
} else {
|
||||||
|
FakeOverrideTypeCalculator.DoNothing
|
||||||
|
}
|
||||||
|
val scope = scope(session, scopeSession, fakeOverrideTypeCalculator, requiredPhase = FirResolvePhase.STATUS) ?: return null
|
||||||
|
var declaredInvoke: FirNamedFunctionSymbol? = null
|
||||||
|
scope.processFunctionsByName(OperatorNameConventions.INVOKE) { functionSymbol ->
|
||||||
|
if (functionSymbol.fir.valueParameters.size == baseInvokeSymbol.fir.valueParameters.size) {
|
||||||
|
declaredInvoke = functionSymbol
|
||||||
|
return@processFunctionsByName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var overriddenInvoke: FirFunctionSymbol<*>? = null
|
||||||
|
if (declaredInvoke != null) {
|
||||||
|
// Make sure the user-contributed or type-substituted invoke we just found above is an override of base invoke.
|
||||||
|
scope.processOverriddenFunctions(declaredInvoke!!) { functionSymbol ->
|
||||||
|
if (functionSymbol == baseInvokeSymbol || functionSymbol.originalForSubstitutionOverride == baseInvokeSymbol) {
|
||||||
|
overriddenInvoke = functionSymbol
|
||||||
|
ProcessorAction.STOP
|
||||||
|
} else {
|
||||||
|
ProcessorAction.NEXT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (overriddenInvoke != null) declaredInvoke else null
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------- functional type type argument extraction ----------------------------------------------
|
||||||
|
|
||||||
|
fun ConeKotlinType.receiverType(session: FirSession): ConeKotlinType? {
|
||||||
|
if (!isSomeFunctionalType(session) || !isExtensionFunctionType(session)) return null
|
||||||
|
return fullyExpandedType(session).let { expanded ->
|
||||||
|
expanded.typeArguments[expanded.contextReceiversNumberForFunctionType].typeOrDefault(session.builtinTypes.nothingType.type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ConeKotlinType.returnType(session: FirSession): ConeKotlinType {
|
||||||
|
require(this is ConeClassLikeType)
|
||||||
|
// TODO: add requirement
|
||||||
|
return fullyExpandedType(session).typeArguments.last().typeOrDefault(session.builtinTypes.nullableAnyType.type)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ConeKotlinType.valueParameterTypesIncludingReceiver(session: FirSession): List<ConeKotlinType> {
|
||||||
|
require(this is ConeClassLikeType)
|
||||||
|
// TODO: add requirement
|
||||||
|
return fullyExpandedType(session).typeArguments.dropLast(1).map { it.typeOrDefault(session.builtinTypes.nothingType.type) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ConeTypeProjection.typeOrDefault(default: ConeKotlinType): ConeKotlinType = when (this) {
|
||||||
|
is ConeKotlinTypeProjection -> type
|
||||||
|
is ConeStarProjection -> default
|
||||||
|
}
|
||||||
@@ -5,27 +5,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.types
|
package org.jetbrains.kotlin.fir.types
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
|
||||||
import org.jetbrains.kotlin.fir.originalForSubstitutionOverride
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||||
import org.jetbrains.kotlin.fir.resolve.scope
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
|
||||||
import kotlin.contracts.ExperimentalContracts
|
import kotlin.contracts.ExperimentalContracts
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
@@ -50,203 +35,10 @@ fun ConeKotlinType.isKMutableProperty(session: FirSession): Boolean {
|
|||||||
classId.shortClassName.identifier.startsWith("KMutableProperty")
|
classId.shortClassName.identifier.startsWith("KMutableProperty")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ConeKotlinType.functionClassKind(session: FirSession): FunctionClassKind? {
|
|
||||||
return classId(session)?.toFunctionClassKind()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ClassId.toFunctionClassKind(): FunctionClassKind? {
|
|
||||||
return FunctionClassKind.byClassNamePrefix(packageFqName, relativeClassName.asString())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function, SuspendFunction, KFunction, KSuspendFunction
|
|
||||||
fun ConeKotlinType.isBuiltinFunctionalType(session: FirSession): Boolean {
|
|
||||||
return functionClassKind(session) != null
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function, SuspendFunction, KFunction, KSuspendFunction
|
|
||||||
fun ConeClassLikeLookupTag.isBuiltinFunctionalType(): Boolean {
|
|
||||||
return classId.toFunctionClassKind() != null
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun ConeKotlinType.isFunctionalType(session: FirSession, predicate: (FunctionClassKind) -> Boolean): Boolean {
|
|
||||||
val kind = functionClassKind(session) ?: return false
|
|
||||||
return predicate(kind)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function
|
|
||||||
fun ConeKotlinType.isFunctionalType(session: FirSession): Boolean {
|
|
||||||
return isFunctionalType(session) { it == FunctionClassKind.Function }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function, SuspendFunction
|
|
||||||
fun ConeKotlinType.isFunctionalOrSuspendFunctionalType(session: FirSession): Boolean {
|
|
||||||
return isFunctionalType(session) { it == FunctionClassKind.Function || it == FunctionClassKind.SuspendFunction }
|
|
||||||
}
|
|
||||||
|
|
||||||
// SuspendFunction, KSuspendFunction
|
|
||||||
fun ConeKotlinType.isSuspendOrKSuspendFunctionType(session: FirSession): Boolean {
|
|
||||||
return isFunctionalType(session) { it.isSuspendType }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ConeKotlinType.isSuspendFunctionType(session: FirSession): Boolean {
|
|
||||||
return isFunctionalType(session) { it == FunctionClassKind.SuspendFunction }
|
|
||||||
}
|
|
||||||
|
|
||||||
// KFunction, KSuspendFunction
|
|
||||||
fun ConeKotlinType.isKFunctionType(session: FirSession): Boolean {
|
|
||||||
return isFunctionalType(session) { it.isReflectType }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ConeKotlinType.kFunctionTypeToFunctionType(session: FirSession): ConeClassLikeType {
|
|
||||||
require(this.isKFunctionType(session))
|
|
||||||
val kind =
|
|
||||||
if (isSuspendOrKSuspendFunctionType(session)) FunctionClassKind.SuspendFunction
|
|
||||||
else FunctionClassKind.Function
|
|
||||||
val functionalTypeId = ClassId(kind.packageFqName, kind.numberedClassName(typeArguments.size - 1))
|
|
||||||
return ConeClassLikeTypeImpl(functionalTypeId.toLookupTag(), typeArguments, isNullable = false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ConeKotlinType.suspendFunctionTypeToFunctionType(session: FirSession): ConeClassLikeType {
|
|
||||||
require(this.isSuspendOrKSuspendFunctionType(session))
|
|
||||||
val kind =
|
|
||||||
if (isKFunctionType(session)) FunctionClassKind.KFunction
|
|
||||||
else FunctionClassKind.Function
|
|
||||||
val functionalTypeId = ClassId(kind.packageFqName, kind.numberedClassName(typeArguments.size - 1))
|
|
||||||
return ConeClassLikeTypeImpl(functionalTypeId.toLookupTag(), typeArguments, isNullable = false, attributes = attributes)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ConeKotlinType.suspendFunctionTypeToFunctionTypeWithContinuation(session: FirSession, continuationClassId: ClassId): ConeClassLikeType {
|
|
||||||
require(this.isSuspendOrKSuspendFunctionType(session))
|
|
||||||
val kind =
|
|
||||||
if (isKFunctionType(session)) FunctionClassKind.KFunction
|
|
||||||
else FunctionClassKind.Function
|
|
||||||
val fullyExpandedType = type.fullyExpandedType(session)
|
|
||||||
val typeArguments = fullyExpandedType.typeArguments
|
|
||||||
val functionalTypeId = ClassId(kind.packageFqName, kind.numberedClassName(typeArguments.size))
|
|
||||||
val lastTypeArgument = typeArguments.last()
|
|
||||||
return ConeClassLikeTypeImpl(
|
|
||||||
functionalTypeId.toLookupTag(),
|
|
||||||
typeArguments = (typeArguments.dropLast(1) + continuationClassId.toLookupTag().constructClassType(
|
|
||||||
arrayOf(lastTypeArgument),
|
|
||||||
isNullable = false
|
|
||||||
) + lastTypeArgument).toTypedArray(),
|
|
||||||
isNullable = fullyExpandedType.isNullable,
|
|
||||||
attributes = fullyExpandedType.attributes
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ConeKotlinType.isSubtypeOfFunctionalType(session: FirSession, expectedFunctionalType: ConeClassLikeType): Boolean {
|
|
||||||
require(expectedFunctionalType.isBuiltinFunctionalType(session))
|
|
||||||
return AbstractTypeChecker.isSubtypeOf(session.typeContext, this, expectedFunctionalType.replaceArgumentsWithStarProjections())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ConeKotlinType.findSubtypeOfNonSuspendFunctionalType(session: FirSession, expectedFunctionalType: ConeClassLikeType): ConeKotlinType? {
|
|
||||||
require(expectedFunctionalType.isBuiltinFunctionalType(session) && !expectedFunctionalType.isSuspendOrKSuspendFunctionType(session))
|
|
||||||
return when (this) {
|
|
||||||
is ConeClassLikeType -> {
|
|
||||||
// Expect the argument type is not a suspend functional type.
|
|
||||||
if (isSuspendOrKSuspendFunctionType(session) || !isSubtypeOfFunctionalType(session, expectedFunctionalType))
|
|
||||||
null
|
|
||||||
else
|
|
||||||
this
|
|
||||||
}
|
|
||||||
is ConeIntersectionType -> {
|
|
||||||
if (intersectedTypes.any { it.isSuspendOrKSuspendFunctionType(session) })
|
|
||||||
null
|
|
||||||
else
|
|
||||||
intersectedTypes.find { it.findSubtypeOfNonSuspendFunctionalType(session, expectedFunctionalType) != null }
|
|
||||||
}
|
|
||||||
is ConeTypeParameterType -> {
|
|
||||||
val bounds = lookupTag.typeParameterSymbol.resolvedBounds.map { it.coneType }
|
|
||||||
if (bounds.any { it.isSuspendOrKSuspendFunctionType(session) })
|
|
||||||
null
|
|
||||||
else
|
|
||||||
bounds.find { it.findSubtypeOfNonSuspendFunctionalType(session, expectedFunctionalType) != null }
|
|
||||||
}
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ConeClassLikeType.findBaseInvokeSymbol(session: FirSession, scopeSession: ScopeSession): FirNamedFunctionSymbol? {
|
|
||||||
require(this.isBuiltinFunctionalType(session))
|
|
||||||
val functionN = (lookupTag.toSymbol(session)?.fir as? FirClass) ?: return null
|
|
||||||
var baseInvokeSymbol: FirNamedFunctionSymbol? = null
|
|
||||||
functionN.unsubstitutedScope(
|
|
||||||
session,
|
|
||||||
scopeSession,
|
|
||||||
withForcedTypeCalculator = false
|
|
||||||
).processFunctionsByName(OperatorNameConventions.INVOKE) { functionSymbol ->
|
|
||||||
baseInvokeSymbol = functionSymbol
|
|
||||||
return@processFunctionsByName
|
|
||||||
}
|
|
||||||
return baseInvokeSymbol
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ConeKotlinType.findContributedInvokeSymbol(
|
|
||||||
session: FirSession,
|
|
||||||
scopeSession: ScopeSession,
|
|
||||||
expectedFunctionalType: ConeClassLikeType,
|
|
||||||
shouldCalculateReturnTypesOfFakeOverrides: Boolean
|
|
||||||
): FirFunctionSymbol<*>? {
|
|
||||||
val baseInvokeSymbol = expectedFunctionalType.findBaseInvokeSymbol(session, scopeSession) ?: return null
|
|
||||||
|
|
||||||
val fakeOverrideTypeCalculator = if (shouldCalculateReturnTypesOfFakeOverrides) {
|
|
||||||
FakeOverrideTypeCalculator.Forced
|
|
||||||
} else {
|
|
||||||
FakeOverrideTypeCalculator.DoNothing
|
|
||||||
}
|
|
||||||
val scope = scope(session, scopeSession, fakeOverrideTypeCalculator, requiredPhase = null) ?: return null
|
|
||||||
var declaredInvoke: FirNamedFunctionSymbol? = null
|
|
||||||
scope.processFunctionsByName(OperatorNameConventions.INVOKE) { functionSymbol ->
|
|
||||||
if (functionSymbol.fir.valueParameters.size == baseInvokeSymbol.fir.valueParameters.size) {
|
|
||||||
declaredInvoke = functionSymbol
|
|
||||||
return@processFunctionsByName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var overriddenInvoke: FirFunctionSymbol<*>? = null
|
|
||||||
if (declaredInvoke != null) {
|
|
||||||
// Make sure the user-contributed or type-substituted invoke we just found above is an override of base invoke.
|
|
||||||
scope.processOverriddenFunctions(declaredInvoke!!) { functionSymbol ->
|
|
||||||
if (functionSymbol == baseInvokeSymbol || functionSymbol.originalForSubstitutionOverride == baseInvokeSymbol) {
|
|
||||||
overriddenInvoke = functionSymbol
|
|
||||||
ProcessorAction.STOP
|
|
||||||
} else {
|
|
||||||
ProcessorAction.NEXT
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return if (overriddenInvoke != null) declaredInvoke else null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ConeKotlinType.isKClassType(): Boolean {
|
fun ConeKotlinType.isKClassType(): Boolean {
|
||||||
return classId == StandardClassIds.KClass
|
return classId == StandardClassIds.KClass
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ConeTypeProjection.typeOrDefault(default: ConeKotlinType): ConeKotlinType =
|
|
||||||
when (this) {
|
|
||||||
is ConeKotlinTypeProjection -> type
|
|
||||||
is ConeStarProjection -> default
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ConeKotlinType.receiverType(session: FirSession): ConeKotlinType? {
|
|
||||||
if (!isBuiltinFunctionalType(session) || !isExtensionFunctionType(session)) return null
|
|
||||||
return fullyExpandedType(session).let { expanded ->
|
|
||||||
expanded.typeArguments[expanded.contextReceiversNumberForFunctionType].typeOrDefault(session.builtinTypes.nothingType.type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ConeKotlinType.returnType(session: FirSession): ConeKotlinType {
|
|
||||||
require(this is ConeClassLikeType)
|
|
||||||
return fullyExpandedType(session).typeArguments.last().typeOrDefault(session.builtinTypes.nullableAnyType.type)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ConeKotlinType.valueParameterTypesIncludingReceiver(session: FirSession): List<ConeKotlinType> {
|
|
||||||
require(this is ConeClassLikeType)
|
|
||||||
return fullyExpandedType(session).typeArguments.dropLast(1).map { it.typeOrDefault(session.builtinTypes.nothingType.type) }
|
|
||||||
}
|
|
||||||
|
|
||||||
val FirAnonymousFunction.returnType: ConeKotlinType? get() = returnTypeRef.coneTypeSafe()
|
val FirAnonymousFunction.returnType: ConeKotlinType? get() = returnTypeRef.coneTypeSafe()
|
||||||
val FirAnonymousFunction.receiverType: ConeKotlinType? get() = receiverParameter?.typeRef?.coneTypeSafe()
|
val FirAnonymousFunction.receiverType: ConeKotlinType? get() = receiverParameter?.typeRef?.coneTypeSafe()
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
|||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer
|
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer
|
||||||
import org.jetbrains.kotlin.fir.types.classId
|
import org.jetbrains.kotlin.fir.types.classId
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
import org.jetbrains.kotlin.fir.types.isBuiltinFunctionalType
|
import org.jetbrains.kotlin.fir.types.isSomeFunctionalType
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode
|
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.OVERLOAD_RESOLUTION_BY_LAMBDA_ANNOTATION_CLASS_ID
|
import org.jetbrains.kotlin.resolve.descriptorUtil.OVERLOAD_RESOLUTION_BY_LAMBDA_ANNOTATION_CLASS_ID
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.same
|
import org.jetbrains.kotlin.utils.addToStdlib.same
|
||||||
@@ -104,7 +104,7 @@ class FirOverloadByLambdaReturnTypeResolver(
|
|||||||
.values.singleOrNull()?.toMap() ?: return null
|
.values.singleOrNull()?.toMap() ?: return null
|
||||||
|
|
||||||
if (!lambdas.values.same { it.parameters.size }) return null
|
if (!lambdas.values.same { it.parameters.size }) return null
|
||||||
if (!lambdas.values.all { it.expectedType?.isBuiltinFunctionalType(session) == true }) return null
|
if (!lambdas.values.all { it.expectedType?.isSomeFunctionalType(session) == true }) return null
|
||||||
|
|
||||||
val originalCalleeReference = call.calleeReference
|
val originalCalleeReference = call.calleeReference
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ import org.jetbrains.kotlin.types.ConstantValueKind
|
|||||||
import org.jetbrains.kotlin.types.SmartcastStability
|
import org.jetbrains.kotlin.types.SmartcastStability
|
||||||
import org.jetbrains.kotlin.types.model.safeSubstitute
|
import org.jetbrains.kotlin.types.model.safeSubstitute
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||||
import kotlin.contracts.ExperimentalContracts
|
import kotlin.contracts.ExperimentalContracts
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
@@ -581,18 +582,15 @@ fun FirFunction.getAsForbiddenNamedArgumentsTarget(
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
// referenced function of a Kotlin function type
|
// referenced function of a Kotlin function type
|
||||||
FirDeclarationOrigin.BuiltIns -> {
|
FirDeclarationOrigin.BuiltIns -> runIf(dispatchReceiverClassLookupTagOrNull()?.isSomeFunctionalType(session) == true) {
|
||||||
if (dispatchReceiverClassLookupTagOrNull()?.isBuiltinFunctionalType() == true) {
|
ForbiddenNamedArgumentsTarget.INVOKE_ON_FUNCTION_TYPE
|
||||||
ForbiddenNamedArgumentsTarget.INVOKE_ON_FUNCTION_TYPE
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
FirDeclarationOrigin.Synthetic -> null
|
|
||||||
FirDeclarationOrigin.DynamicScope -> null
|
FirDeclarationOrigin.Synthetic,
|
||||||
FirDeclarationOrigin.RenamedForOverride -> null
|
FirDeclarationOrigin.DynamicScope,
|
||||||
FirDeclarationOrigin.WrappedIntegerOperator -> null
|
FirDeclarationOrigin.RenamedForOverride,
|
||||||
FirDeclarationOrigin.ScriptCustomization -> null
|
FirDeclarationOrigin.WrappedIntegerOperator,
|
||||||
|
FirDeclarationOrigin.ScriptCustomization,
|
||||||
is FirDeclarationOrigin.Plugin -> null // TODO: figure out what to do with plugin generated functions
|
is FirDeclarationOrigin.Plugin -> null // TODO: figure out what to do with plugin generated functions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -293,9 +293,9 @@ private fun argumentTypeWithSuspendConversion(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We want to check the argument type against non-suspend functional type.
|
// We want to check the argument type against non-suspend functional type.
|
||||||
val expectedFunctionalType = expectedType.suspendFunctionTypeToFunctionType(session)
|
val expectedFunctionalType = expectedType.customFunctionalTypeToSimpleFunctionalType(session)
|
||||||
|
|
||||||
val argumentTypeWithInvoke = argumentType.findSubtypeOfNonSuspendFunctionalType(session, expectedFunctionalType)
|
val argumentTypeWithInvoke = argumentType.findSubtypeOfSimpleFunctionalType(session, expectedFunctionalType)
|
||||||
|
|
||||||
return argumentTypeWithInvoke?.findContributedInvokeSymbol(
|
return argumentTypeWithInvoke?.findContributedInvokeSymbol(
|
||||||
session,
|
session,
|
||||||
@@ -308,7 +308,7 @@ private fun argumentTypeWithSuspendConversion(
|
|||||||
null,
|
null,
|
||||||
invokeSymbol.fir.returnTypeRef.coneType,
|
invokeSymbol.fir.returnTypeRef.coneType,
|
||||||
isSuspend = true,
|
isSuspend = true,
|
||||||
isKFunctionType = argumentType.isKFunctionType(session)
|
isKFunctionType = argumentType.isReflectFunctionalType(session)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -498,7 +498,7 @@ private fun Candidate.getExpectedTypeWithSAMConversion(
|
|||||||
candidateExpectedType: ConeKotlinType,
|
candidateExpectedType: ConeKotlinType,
|
||||||
context: ResolutionContext
|
context: ResolutionContext
|
||||||
): ConeKotlinType? {
|
): ConeKotlinType? {
|
||||||
if (candidateExpectedType.isBuiltinFunctionalType(session)) return null
|
if (candidateExpectedType.isSomeFunctionalType(session)) return null
|
||||||
|
|
||||||
// TODO: resolvedCall.registerArgumentWithSamConversion(argument, SamConversionDescription(convertedTypeByOriginal, convertedTypeByCandidate!!))
|
// TODO: resolvedCall.registerArgumentWithSamConversion(argument, SamConversionDescription(convertedTypeByOriginal, convertedTypeByCandidate!!))
|
||||||
|
|
||||||
@@ -521,7 +521,7 @@ fun FirExpression.isFunctional(
|
|||||||
else -> {
|
else -> {
|
||||||
// Either a functional type or a subtype of a class that has a contributed `invoke`.
|
// Either a functional type or a subtype of a class that has a contributed `invoke`.
|
||||||
val coneType = typeRef.coneTypeSafe<ConeKotlinType>() ?: return false
|
val coneType = typeRef.coneTypeSafe<ConeKotlinType>() ?: return false
|
||||||
if (coneType.isBuiltinFunctionalType(session)) {
|
if (coneType.isSomeFunctionalType(session)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
val classLikeExpectedFunctionType = expectedFunctionType?.lowerBoundIfFlexible() as? ConeClassLikeType
|
val classLikeExpectedFunctionType = expectedFunctionType?.lowerBoundIfFlexible() as? ConeClassLikeType
|
||||||
|
|||||||
@@ -297,7 +297,7 @@ object CheckDslScopeViolation : ResolutionStage() {
|
|||||||
// ```
|
// ```
|
||||||
// `useX()` is a call to `invoke` with `useX` as the dispatch receiver. In the FIR tree, extension receiver is represented as an
|
// `useX()` is a call to `invoke` with `useX` as the dispatch receiver. In the FIR tree, extension receiver is represented as an
|
||||||
// implicit `this` expression passed as the first argument.
|
// implicit `this` expression passed as the first argument.
|
||||||
if (candidate.dispatchReceiverValue?.type?.fullyExpandedType(context.session)?.isBuiltinFunctionalType(context.session) == true &&
|
if (candidate.dispatchReceiverValue?.type?.fullyExpandedType(context.session)?.isSomeFunctionalType(context.session) == true &&
|
||||||
(candidate.symbol as? FirNamedFunctionSymbol)?.name == OperatorNameConventions.INVOKE
|
(candidate.symbol as? FirNamedFunctionSymbol)?.name == OperatorNameConventions.INVOKE
|
||||||
) {
|
) {
|
||||||
val firstArg = candidate.argumentMapping?.keys?.firstOrNull() as? FirThisReceiverExpression ?: return
|
val firstArg = candidate.argumentMapping?.keys?.firstOrNull() as? FirThisReceiverExpression ?: return
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ fun extractLambdaInfoFromFunctionalType(
|
|||||||
duringCompletion
|
duringCompletion
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (!expectedType.isBuiltinFunctionalType(session)) return null
|
if (!expectedType.isSomeFunctionalType(session)) return null
|
||||||
|
|
||||||
val singleStatement = argument.body?.statements?.singleOrNull() as? FirReturnExpression
|
val singleStatement = argument.body?.statements?.singleOrNull() as? FirReturnExpression
|
||||||
if (argument.returnType == null && singleStatement != null &&
|
if (argument.returnType == null && singleStatement != null &&
|
||||||
|
|||||||
+1
-1
@@ -109,7 +109,7 @@ private fun extractLambdaInfo(
|
|||||||
|
|
||||||
val isFunctionSupertype =
|
val isFunctionSupertype =
|
||||||
expectedType != null && expectedType.lowerBoundIfFlexible()
|
expectedType != null && expectedType.lowerBoundIfFlexible()
|
||||||
.isBuiltinFunctionalType(session)//isNotNullOrNullableFunctionSupertype(expectedType)
|
.isSomeFunctionalType(session)//isNotNullOrNullableFunctionSupertype(expectedType)
|
||||||
|
|
||||||
val typeVariable = ConeTypeVariableForLambdaReturnType(argument, "_L")
|
val typeVariable = ConeTypeVariableForLambdaReturnType(argument, "_L")
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -177,7 +177,7 @@ internal fun extractInputOutputTypesFromCallableReferenceExpectedType(
|
|||||||
if (expectedType == null) return null
|
if (expectedType == null) return null
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
expectedType.isBuiltinFunctionalType(session) ->
|
expectedType.isSomeFunctionalType(session) ->
|
||||||
InputOutputTypes(expectedType.valueParameterTypesIncludingReceiver(session), expectedType.returnType(session))
|
InputOutputTypes(expectedType.valueParameterTypesIncludingReceiver(session), expectedType.returnType(session))
|
||||||
|
|
||||||
// ReflectionTypes.isBaseTypeForNumberedReferenceTypes(expectedType) ->
|
// ReflectionTypes.isBaseTypeForNumberedReferenceTypes(expectedType) ->
|
||||||
|
|||||||
+1
-1
@@ -561,7 +561,7 @@ class FirCallCompletionResultsWriterTransformer(
|
|||||||
// From the argument mapping, the expected type of this anonymous function would be:
|
// From the argument mapping, the expected type of this anonymous function would be:
|
||||||
when {
|
when {
|
||||||
// a built-in functional type, no-brainer
|
// a built-in functional type, no-brainer
|
||||||
expectedArgumentType.isBuiltinFunctionalType(session) -> expectedArgumentType
|
expectedArgumentType.isSomeFunctionalType(session) -> expectedArgumentType
|
||||||
// fun interface (a.k.a. SAM), then unwrap it and build a functional type from that interface function
|
// fun interface (a.k.a. SAM), then unwrap it and build a functional type from that interface function
|
||||||
expectedArgumentType is ConeClassLikeType -> {
|
expectedArgumentType is ConeClassLikeType -> {
|
||||||
val firRegularClass =
|
val firRegularClass =
|
||||||
|
|||||||
+2
-2
@@ -19,7 +19,7 @@ import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
|||||||
import org.jetbrains.kotlin.fir.expressions.FirWrappedArgumentExpression
|
import org.jetbrains.kotlin.fir.expressions.FirWrappedArgumentExpression
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
import org.jetbrains.kotlin.fir.types.isFunctionalOrSuspendFunctionalType
|
import org.jetbrains.kotlin.fir.types.isNonReflectFunctionalType
|
||||||
|
|
||||||
tailrec fun FirExpression.unwrapAnonymousFunctionExpression(): FirAnonymousFunction? = when (this) {
|
tailrec fun FirExpression.unwrapAnonymousFunctionExpression(): FirAnonymousFunction? = when (this) {
|
||||||
is FirAnonymousFunctionExpression -> anonymousFunction
|
is FirAnonymousFunctionExpression -> anonymousFunction
|
||||||
@@ -47,7 +47,7 @@ fun FirFunctionCall.replaceLambdaArgumentInvocationKinds(session: FirSession) {
|
|||||||
val kind = byParameter[parameter] ?: EventOccurrencesRange.UNKNOWN.takeIf {
|
val kind = byParameter[parameter] ?: EventOccurrencesRange.UNKNOWN.takeIf {
|
||||||
// Inline functional parameters have to be called in-place; that's the only permitted operation on them.
|
// Inline functional parameters have to be called in-place; that's the only permitted operation on them.
|
||||||
isInline && !parameter.isNoinline && !parameter.isCrossinline &&
|
isInline && !parameter.isNoinline && !parameter.isCrossinline &&
|
||||||
parameter.returnTypeRef.coneType.isFunctionalOrSuspendFunctionalType(session)
|
parameter.returnTypeRef.coneType.isNonReflectFunctionalType(session)
|
||||||
} ?: continue
|
} ?: continue
|
||||||
lambda.replaceInvocationKind(kind)
|
lambda.replaceInvocationKind(kind)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -39,7 +39,6 @@ import org.jetbrains.kotlin.fir.resolve.transformers.FirCallCompletionResultsWri
|
|||||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirStatusResolver
|
import org.jetbrains.kotlin.fir.resolve.transformers.FirStatusResolver
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.transformVarargTypeToArrayType
|
import org.jetbrains.kotlin.fir.resolve.transformers.transformVarargTypeToArrayType
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
|
||||||
import org.jetbrains.kotlin.fir.types.constructStarProjectedType
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
|
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
|
||||||
@@ -859,7 +858,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve
|
|||||||
lambda: FirAnonymousFunction
|
lambda: FirAnonymousFunction
|
||||||
): List<FirValueParameter> {
|
): List<FirValueParameter> {
|
||||||
if (expectedType == null) return lambda.valueParameters
|
if (expectedType == null) return lambda.valueParameters
|
||||||
if (!expectedType.isFunctionalOrSuspendFunctionalType(session)) return lambda.valueParameters
|
if (!expectedType.isNonReflectFunctionalType(session)) return lambda.valueParameters
|
||||||
val parameterTypes = expectedType.typeArguments
|
val parameterTypes = expectedType.typeArguments
|
||||||
.mapTo(mutableListOf()) { it.type ?: session.builtinTypes.nullableAnyType.type }
|
.mapTo(mutableListOf()) { it.type ?: session.builtinTypes.nullableAnyType.type }
|
||||||
.also { it.removeLastOrNull() }
|
.also { it.removeLastOrNull() }
|
||||||
|
|||||||
@@ -742,7 +742,13 @@ class FirRenderer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef) {
|
override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef) {
|
||||||
typeRenderer.renderAsPossibleFunctionType(resolvedTypeRef.type)
|
typeRenderer.renderAsPossibleFunctionType(
|
||||||
|
resolvedTypeRef.type,
|
||||||
|
l@{
|
||||||
|
val classId = it.classId ?: return@l null
|
||||||
|
FirFunctionalTypeKindService.Default.getKindByClassNamePrefix(classId.packageFqName, classId.shortClassName.asString())
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitUserTypeRef(userTypeRef: FirUserTypeRef) {
|
override fun visitUserTypeRef(userTypeRef: FirUserTypeRef) {
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.types
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
|
abstract class FirFunctionalTypeKindService : FirSessionComponent {
|
||||||
|
abstract fun getKindByClassNamePrefix(packageFqName: FqName, className: String): ConeFunctionalTypeKind?
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Should be used only in places where session is unavaliable by default (e.g. in default cone type render)
|
||||||
|
*/
|
||||||
|
object Default : FirFunctionalTypeKindService() {
|
||||||
|
override fun getKindByClassNamePrefix(packageFqName: FqName, className: String): ConeFunctionalTypeKind? {
|
||||||
|
return when (FunctionClassKind.parseClassName(className, packageFqName)?.kind) {
|
||||||
|
FunctionClassKind.Function -> ConeFunctionalTypeKind.Function
|
||||||
|
FunctionClassKind.SuspendFunction -> ConeFunctionalTypeKind.SuspendFunction
|
||||||
|
FunctionClassKind.KFunction -> ConeFunctionalTypeKind.KFunction
|
||||||
|
FunctionClassKind.KSuspendFunction -> ConeFunctionalTypeKind.KSuspendFunction
|
||||||
|
null -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val FirSession.functionalTypeService: FirFunctionalTypeKindService by FirSession.sessionComponentAccessor()
|
||||||
+4
-1
@@ -337,7 +337,10 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
val projectionBuilder = StringBuilder()
|
val projectionBuilder = StringBuilder()
|
||||||
ConeTypeRendererForDebugging(projectionBuilder).renderAsPossibleFunctionType(this) {
|
ConeTypeRendererForDebugging(projectionBuilder).renderAsPossibleFunctionType(
|
||||||
|
this,
|
||||||
|
{ it.functionalTypeKind(session) }
|
||||||
|
) {
|
||||||
localTypeProjectionRenderer(projectionBuilder)
|
localTypeProjectionRenderer(projectionBuilder)
|
||||||
}
|
}
|
||||||
builder.append(projectionBuilder.toString().removeCurrentFilePackage())
|
builder.append(projectionBuilder.toString().removeCurrentFilePackage())
|
||||||
|
|||||||
+1
-1
@@ -114,7 +114,7 @@ object FirParcelizePropertyChecker : FirPropertyChecker() {
|
|||||||
type.anySuperTypeConstructor {
|
type.anySuperTypeConstructor {
|
||||||
it is ConeKotlinType &&
|
it is ConeKotlinType &&
|
||||||
(it.classId?.asFqNameString() in BuiltinParcelableTypes.PARCELABLE_SUPERTYPE_FQNAMES ||
|
(it.classId?.asFqNameString() in BuiltinParcelableTypes.PARCELABLE_SUPERTYPE_FQNAMES ||
|
||||||
it.isBuiltinFunctionalType(session))
|
it.isSomeFunctionalType(session))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user