[FIR] Generify resolution and inference of arguments of functional types

This commit is contained in:
Dmitriy Novozhilov
2023-01-18 17:29:41 +02:00
committed by Space Team
parent 67aa80562d
commit d1b797ed97
26 changed files with 219 additions and 145 deletions
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirSafe
import org.jetbrains.kotlin.analysis.utils.errors.unexpectedElementError
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
@@ -114,7 +113,7 @@ internal class KtFirExpressionTypeProvider(
declaration.toFirAnonymousFunction()
else
declaration.getOrBuildFirOfType<FirFunction>(firResolveSession)
return firFunction.constructFunctionalType(firFunction.isSuspend).asKtType()
return firFunction.constructFunctionalType(firFunction.specialFunctionalTypeKind(firResolveSession.useSiteFirSession)).asKtType()
}
@OptIn(ExperimentalContracts::class)
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.scopes.collectAllFunctions
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverrideFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.isSuspendFunctionType
import org.jetbrains.kotlin.fir.types.typeContext
object FirJsInheritanceClassChecker : FirClassChecker() {
@@ -52,7 +53,7 @@ object FirJsInheritanceClassChecker : FirClassChecker() {
}
private fun ConeClassLikeType.isSuspendFunctionTypeOrSubtype(session: FirSession): Boolean {
return with(session.typeContext) { isSuspendFunctionTypeOrSubtype() }
return with(session.typeContext) { isTypeOrSubtypeOf { it.isSuspendFunctionType(session) } }
}
private fun FirClass.findFakeMethodOverridingExternalWithOptionalParams(context: CheckerContext): FirNamedFunctionSymbol? {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.types
import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
@@ -466,7 +467,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
return this.isSomeFunctionalType(session)
}
private fun ConeKotlinType.isTypeOrSubtypeOf(predicate: (ConeKotlinType) -> Boolean): Boolean {
fun ConeKotlinType.isTypeOrSubtypeOf(predicate: (ConeKotlinType) -> Boolean): Boolean {
return predicate(this) || DFS.dfsFromNode(
this,
{
@@ -489,13 +490,6 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
)
}
override fun KotlinTypeMarker.isSuspendFunctionTypeOrSubtype(): Boolean {
require(this is ConeKotlinType)
return isTypeOrSubtypeOf {
(it.lowerBoundIfFlexible() as ConeKotlinType).isSuspendOrKSuspendFunctionType(session)
}
}
override fun KotlinTypeMarker.isExtensionFunctionType(): Boolean {
require(this is ConeKotlinType)
return (this.lowerBoundIfFlexible() as? ConeKotlinType)?.isExtensionFunctionType(session) == true
@@ -536,24 +530,17 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
}
}
override fun getFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker {
val classId = if (isSuspend) {
StandardClassIds.SuspendFunctionN(parametersNumber)
} else {
StandardClassIds.FunctionN(parametersNumber)
}
return session.symbolProvider.getClassLikeSymbolByClassId(classId)?.toLookupTag()
?: error("Can't find Function type")
override fun KotlinTypeMarker.functionalTypeKind(): FunctionalTypeKind? {
require(this is ConeKotlinType)
return this.functionalTypeKind(session)
}
override fun getKFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker {
val classId = if (isSuspend) {
StandardClassIds.KSuspendFunctionN(parametersNumber)
} else {
StandardClassIds.KFunctionN(parametersNumber)
}
return session.symbolProvider.getClassLikeSymbolByClassId(classId)?.toLookupTag()
?: error("Can't find KFunction type")
override fun getNonReflectFunctionTypeConstructor(parametersNumber: Int, kind: FunctionalTypeKind): TypeConstructorMarker {
return kind.nonReflectKind().numberedClassId(parametersNumber).toLookupTag()
}
override fun getReflectFunctionTypeConstructor(parametersNumber: Int, kind: FunctionalTypeKind): TypeConstructorMarker {
return kind.reflectKind().numberedClassId(parametersNumber).toLookupTag()
}
override fun createTypeWithAlternativeForIntersectionResult(
@@ -8,11 +8,15 @@ package org.jetbrains.kotlin.fir.types
import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKind
import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKindExtractor
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
import org.jetbrains.kotlin.fir.extensions.FirFunctionalTypeKindExtension
import org.jetbrains.kotlin.fir.extensions.extensionService
import org.jetbrains.kotlin.fir.extensions.functionalTypeKindExtensions
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
class FirFunctionalTypeKindServiceImpl(session: FirSession) : FirFunctionalTypeKindService() {
private val nonReflectKindsFromExtensions = mutableListOf<FunctionalTypeKind>()
override val extractor: FunctionalTypeKindExtractor = run {
val kinds = buildList {
add(FunctionalTypeKind.Function)
@@ -26,6 +30,7 @@ class FirFunctionalTypeKindServiceImpl(session: FirSession) : FirFunctionalTypeK
require(reflectKind.nonReflectKind() == nonReflectKind)
add(nonReflectKind)
add(reflectKind)
nonReflectKindsFromExtensions += nonReflectKind
}
}
@@ -38,6 +43,31 @@ class FirFunctionalTypeKindServiceImpl(session: FirSession) : FirFunctionalTypeK
"There are clashing functional type kinds: $allNames"
}
}
FunctionalTypeKindExtractor(kinds)
}
override fun extractSingleSpecialKindForFunction(functionSymbol: FirNamedFunctionSymbol): FunctionalTypeKind? {
if (nonReflectKindsFromExtensions.isEmpty()) {
return FunctionalTypeKind.SuspendFunction.takeIf { functionSymbol.isSuspend }
}
return extractAllSpecialKindsForFunction(functionSymbol).singleOrNull()
}
override fun extractAllSpecialKindsForFunction(functionSymbol: FirNamedFunctionSymbol): List<FunctionalTypeKind> {
return buildList {
if (functionSymbol.isSuspend) {
add(FunctionalTypeKind.SuspendFunction)
}
if (nonReflectKindsFromExtensions.isNotEmpty()) {
for (annotationClassId in functionSymbol.resolvedAnnotationClassIds) {
for (kind in nonReflectKindsFromExtensions) {
if (kind.annotationOnInvokeClassId == annotationClassId) {
add(kind)
}
}
}
}
}
}
}
@@ -6,8 +6,10 @@
package org.jetbrains.kotlin.fir.types
import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKind
import org.jetbrains.kotlin.builtins.functions.isRegularFunction
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.originalForSubstitutionOverride
import org.jetbrains.kotlin.fir.resolve.ScopeSession
@@ -82,14 +84,12 @@ fun ConeClassLikeLookupTag.isSomeFunctionalType(session: FirSession): Boolean {
// Function, KFunction
private fun ConeKotlinType.isSimpleFunctionalType(session: FirSession, errorOnNotFunctionalType: Boolean): Boolean {
return isFunctionalTypeWithPredicate(session, errorOnNotFunctionalType) {
it == FunctionalTypeKind.Function || it == FunctionalTypeKind.KFunction
}
return isFunctionalTypeWithPredicate(session, errorOnNotFunctionalType) { it.isRegularFunction }
}
// SuspendFunction, [Custom]Function, KSuspendFunction, K[Custom]Function
private fun ConeKotlinType.isNotSimpleFunctionalType(session: FirSession): Boolean {
return !isSimpleFunctionalType(session, errorOnNotFunctionalType = false)
fun ConeKotlinType.isNotSimpleFunctionalType(session: FirSession): Boolean {
return isFunctionalTypeWithPredicate(session, errorOnNotFunctionalType = false) { !it.isRegularFunction }
}
// ---------------------------------------------- functional type conversions ----------------------------------------------
@@ -106,7 +106,7 @@ fun ConeKotlinType.customFunctionalTypeToSimpleFunctionalType(session: FirSessio
} else {
FunctionalTypeKind.Function
}
return createFunctionalTypeWithNewKind(newKind)
return createFunctionalTypeWithNewKind(session, newKind)
}
/*
@@ -117,12 +117,17 @@ fun ConeKotlinType.customFunctionalTypeToSimpleFunctionalType(session: FirSessio
fun ConeKotlinType.reflectFunctionalTypeToNonReflectFunctionalType(session: FirSession): ConeClassLikeType {
val kind = functionalTypeKind(session)
require(kind != null && kind.isReflectType)
return createFunctionalTypeWithNewKind(kind.nonReflectKind())
return createFunctionalTypeWithNewKind(session, kind.nonReflectKind())
}
private fun ConeKotlinType.createFunctionalTypeWithNewKind(kind: FunctionalTypeKind): ConeClassLikeType {
val functionalTypeId = ClassId(kind.packageFqName, kind.numberedClassName(typeArguments.size - 1))
return functionalTypeId.toLookupTag().constructClassType(typeArguments, isNullable = false, attributes = attributes)
private fun ConeKotlinType.createFunctionalTypeWithNewKind(session: FirSession, kind: FunctionalTypeKind): ConeClassLikeType {
val expandedType = fullyExpandedType(session)
val functionalTypeId = ClassId(kind.packageFqName, kind.numberedClassName(expandedType.typeArguments.size - 1))
return functionalTypeId.toLookupTag().constructClassType(
expandedType.typeArguments,
isNullable = false,
attributes = expandedType.attributes
)
}
// ---------------------------------------------- functional type subtyping ----------------------------------------------
@@ -139,8 +144,8 @@ private fun ConeKotlinType.findSubtypeOfSimpleFunctionalTypeImpl(
): ConeKotlinType? {
return when (this) {
is ConeClassLikeType -> {
// Expect the argument type is a simple functional type.
when {
// Expect the argument type is a simple functional type.
isNotSimpleFunctionalType(session) -> null
isSubtypeOfFunctionalType(session, expectedFunctionalType) -> this
else -> null
@@ -247,3 +252,11 @@ private fun ConeTypeProjection.typeOrDefault(default: ConeKotlinType): ConeKotli
is ConeKotlinTypeProjection -> type
is ConeStarProjection -> default
}
// ----------------- TODO fir utils
fun FirFunction.specialFunctionalTypeKind(session: FirSession): FunctionalTypeKind? {
return (symbol as? FirNamedFunctionSymbol)?.let {
session.functionalTypeService.extractSingleSpecialKindForFunction(it)
}
}
@@ -60,15 +60,9 @@ import org.jetbrains.kotlin.utils.addToStdlib.runIf
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
fun List<FirQualifierPart>.toTypeProjections(): Array<ConeTypeProjection> =
asReversed().flatMap { it.typeArgumentList.typeArguments.map { typeArgument -> typeArgument.toConeTypeProjection() } }.toTypedArray()
fun FirAnonymousFunction.shouldReturnUnit(returnStatements: Collection<FirExpression>): Boolean =
isLambda && returnStatements.any { it is FirUnitExpression }
fun FirAnonymousFunction.isExplicitlySuspend(session: FirSession): Boolean =
typeRef.coneTypeSafe<ConeKotlinType>()?.isSuspendOrKSuspendFunctionType(session) == true
fun FirAnonymousFunction.addReturnToLastStatementIfNeeded() {
// If this lambda's resolved, expected return type is Unit, we don't need an explicit return statement.
// During conversion (to backend IR), the last expression will be coerced to Unit if needed.
@@ -96,7 +90,10 @@ fun FirAnonymousFunction.addReturnToLastStatementIfNeeded() {
)
}
fun FirFunction.constructFunctionalType(isSuspend: Boolean = false): ConeLookupTagBasedType {
/**
* [kind] == null means that [FunctionalTypeKind.Function] will be used
*/
fun FirFunction.constructFunctionalType(kind: FunctionalTypeKind? = null): ConeLookupTagBasedType {
val receiverTypeRef = when (this) {
is FirSimpleFunction -> receiverParameter
is FirAnonymousFunction -> receiverParameter
@@ -114,25 +111,27 @@ fun FirFunction.constructFunctionalType(isSuspend: Boolean = false): ConeLookupT
val rawReturnType = (this as FirCallableDeclaration).returnTypeRef.coneType
return createFunctionalType(
parameters, receiverTypeRef?.coneType, rawReturnType, isSuspend = isSuspend,
kind ?: FunctionalTypeKind.Function, parameters, receiverTypeRef?.coneType, rawReturnType,
contextReceivers = contextReceivers.map { it.typeRef.coneType }
)
}
fun FirFunction.constructFunctionalTypeRef(isSuspend: Boolean = false): FirResolvedTypeRef {
/**
* [kind] == null means that [FunctionalTypeKind.Function] will be used
*/
fun FirFunction.constructFunctionalTypeRef(kind: FunctionalTypeKind? = null): FirResolvedTypeRef {
return buildResolvedTypeRef {
source = this@constructFunctionalTypeRef.source?.fakeElement(KtFakeSourceElementKind.ImplicitTypeRef)
type = constructFunctionalType(isSuspend)
type = constructFunctionalType(kind)
}
}
fun createFunctionalType(
kind: FunctionalTypeKind,
parameters: List<ConeKotlinType>,
receiverType: ConeKotlinType?,
rawReturnType: ConeKotlinType,
isSuspend: Boolean,
contextReceivers: List<ConeKotlinType> = emptyList(),
isKFunctionType: Boolean = false
): ConeLookupTagBasedType {
val receiverAndParameterTypes =
buildList {
@@ -142,12 +141,6 @@ fun createFunctionalType(
add(rawReturnType)
}
val kind = if (isSuspend) {
if (isKFunctionType) FunctionalTypeKind.KSuspendFunction else FunctionalTypeKind.SuspendFunction
} else {
if (isKFunctionType) FunctionalTypeKind.KFunction else FunctionalTypeKind.Function
}
val functionalTypeId = ClassId(kind.packageFqName, kind.numberedClassName(receiverAndParameterTypes.size - 1))
val attributes = when {
contextReceivers.isNotEmpty() -> ConeAttributes.create(
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.resolve
import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKind
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
import org.jetbrains.kotlin.descriptors.Modality
@@ -265,7 +266,7 @@ class FirSamResolver(
it.getCustomFunctionalTypeForSamConversion(abstractMethod)
}
SAMInfo(abstractMethod.symbol, typeFromExtension ?: abstractMethod.getFunctionTypeForAbstractMethod())
SAMInfo(abstractMethod.symbol, typeFromExtension ?: abstractMethod.getFunctionTypeForAbstractMethod(session))
}
}
@@ -407,18 +408,19 @@ fun FirSimpleFunction.isPublicInObject(checkOnlyName: Boolean): Boolean {
private val PUBLIC_METHOD_NAMES_IN_OBJECT = setOf("equals", "hashCode", "getClass", "wait", "notify", "notifyAll", "toString")
private fun FirSimpleFunction.getFunctionTypeForAbstractMethod(): ConeLookupTagBasedType {
private fun FirSimpleFunction.getFunctionTypeForAbstractMethod(session: FirSession): ConeLookupTagBasedType {
val parameterTypes = valueParameters.map {
it.returnTypeRef.coneTypeSafe<ConeKotlinType>() ?: ConeErrorType(ConeIntermediateDiagnostic("No type for parameter $it"))
}
val contextReceiversTypes = contextReceivers.map {
it.typeRef.coneTypeSafe<ConeKotlinType>() ?: ConeErrorType(ConeIntermediateDiagnostic("No type for context receiver $it"))
}
val kind = session.functionalTypeService.extractSingleSpecialKindForFunction(symbol) ?: FunctionalTypeKind.Function
return createFunctionalType(
kind,
parameterTypes,
receiverType = receiverParameter?.typeRef?.coneType,
rawReturnType = returnTypeRef.coneType,
isSuspend = this.isSuspend,
contextReceivers = contextReceiversTypes
)
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.builtins.functions.isRegularFunction
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
@@ -265,12 +266,12 @@ fun Candidate.resolvePlainArgumentType(
// If the argument is of functional type and the expected type is a suspend function type, we need to do "suspend conversion."
if (expectedType != null) {
argumentTypeWithSuspendConversion(
argumentTypeWithCustomConversion(
session, context.bodyResolveComponents.scopeSession, expectedType, argumentTypeForApplicabilityCheck
)?.let {
argumentTypeForApplicabilityCheck = it
substitutor.substituteOrSelf(argumentTypeForApplicabilityCheck)
usesSuspendConversion = true
usesFunctionalConversion = true
}
}
@@ -279,18 +280,15 @@ fun Candidate.resolvePlainArgumentType(
)
}
private fun argumentTypeWithSuspendConversion(
private fun argumentTypeWithCustomConversion(
session: FirSession,
scopeSession: ScopeSession,
expectedType: ConeKotlinType,
argumentType: ConeKotlinType
): ConeKotlinType? {
// TODO: should refer to LanguageVersionSettings.SuspendConversion
// Expect the expected type to be a suspend functional type.
if (!expectedType.isSuspendOrKSuspendFunctionType(session)) {
return null
}
// Expect the expected type to be a not regular functional type (e.g. suspend or custom)
val expectedTypeKind = expectedType.functionalTypeKind(session) ?: return null
if (expectedTypeKind.isRegularFunction) return null
// We want to check the argument type against non-suspend functional type.
val expectedFunctionalType = expectedType.customFunctionalTypeToSimpleFunctionalType(session)
@@ -304,11 +302,10 @@ private fun argumentTypeWithSuspendConversion(
shouldCalculateReturnTypesOfFakeOverrides = false
)?.let { invokeSymbol ->
createFunctionalType(
expectedTypeKind,
invokeSymbol.fir.valueParameters.map { it.returnTypeRef.coneType },
null,
invokeSymbol.fir.returnTypeRef.coneType,
isSuspend = true,
isKFunctionType = argumentType.isReflectFunctionalType(session)
)
}
}
@@ -7,10 +7,11 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKind
import org.jetbrains.kotlin.builtins.functions.isRegularFunction
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
@@ -26,7 +27,6 @@ import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.resolve.calls.components.SuspendConversionStrategy
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.runTransaction
@@ -130,14 +130,16 @@ private fun buildReflectionType(
fir.valueParameters.mapTo(parameters) { it.returnTypeRef.coneType }
}
val isSuspend = (fir as? FirSimpleFunction)?.isSuspend == true ||
callableReferenceAdaptation?.suspendConversionStrategy == SuspendConversionStrategy.SUSPEND_CONVERSION
val baseFunctionalTypeKind = callableReferenceAdaptation?.suspendConversionStrategy?.kind
?: fir.specialFunctionalTypeKind(context.session)
?: FunctionalTypeKind.Function
return createFunctionalType(
baseFunctionalTypeKind.reflectKind(),
parameters,
receiverType = receiverType.takeIf { fir.receiverParameter != null },
rawReturnType = returnType,
isKFunctionType = true,
isSuspend = isSuspend,
contextReceivers = fir.contextReceivers.map { it.typeRef.coneType }
) to callableReferenceAdaptation
}
@@ -151,14 +153,14 @@ internal class CallableReferenceAdaptation(
val coercionStrategy: CoercionStrategy,
val defaults: Int,
val mappedArguments: CallableReferenceMappedArguments,
val suspendConversionStrategy: SuspendConversionStrategy
val suspendConversionStrategy: CallableReferenceConversionStrategy
)
private fun CallableReferenceAdaptation?.needCompatibilityResolveForCallableReference(): Boolean {
// KT-13934: check containing declaration for companion object
if (this == null) return false
return defaults != 0 ||
suspendConversionStrategy != SuspendConversionStrategy.NO_CONVERSION ||
suspendConversionStrategy != CallableReferenceConversionStrategy.NoConversion ||
coercionStrategy != CoercionStrategy.NO_COERCION ||
mappedArguments.values.any { it is ResolvedCallArgument.VarargArgument }
}
@@ -253,10 +255,14 @@ private fun BodyResolveComponents.getCallableReferenceAdaptation(
else
mappedArguments
val suspendConversionStrategy = if ((function as? FirSimpleFunction)?.isSuspend != true && expectedType.isSuspendOrKSuspendFunctionType(session))
SuspendConversionStrategy.SUSPEND_CONVERSION
else
SuspendConversionStrategy.NO_CONVERSION
val expectedTypeFunctionalKind = expectedType.functionalTypeKind(session)?.takeUnless { it.isRegularFunction }
val functionKind = function.specialFunctionalTypeKind(session)
val conversionStrategy = if (expectedTypeFunctionalKind != null && functionKind == null) {
CallableReferenceConversionStrategy.CustomConversion(expectedTypeFunctionalKind)
} else {
CallableReferenceConversionStrategy.NoConversion
}
@Suppress("UNCHECKED_CAST")
return CallableReferenceAdaptation(
@@ -264,10 +270,23 @@ private fun BodyResolveComponents.getCallableReferenceAdaptation(
coercionStrategy,
defaults,
adaptedArguments,
suspendConversionStrategy
conversionStrategy
)
}
sealed class CallableReferenceConversionStrategy {
abstract val kind: FunctionalTypeKind?
object NoConversion : CallableReferenceConversionStrategy() {
override val kind: FunctionalTypeKind?
get() = null
}
class CustomConversion(override val kind: FunctionalTypeKind) : CallableReferenceConversionStrategy()
}
private fun varargParameterTypeByExpectedParameter(
expectedParameterType: ConeKotlinType,
substitutedParameter: FirValueParameter,
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeTypeVariable
import org.jetbrains.kotlin.resolve.calls.components.SuspendConversionStrategy
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintSystemError
@@ -63,13 +62,13 @@ class Candidate(
internal var callableReferenceAdaptation: CallableReferenceAdaptation? = null
set(value) {
field = value
usesSuspendConversion = value?.suspendConversionStrategy == SuspendConversionStrategy.SUSPEND_CONVERSION
usesFunctionalConversion = value?.suspendConversionStrategy is CallableReferenceConversionStrategy.CustomConversion
if (value != null) {
numDefaults = value.defaults
}
}
var usesSuspendConversion: Boolean = false
var usesFunctionalConversion: Boolean = false
var argumentMapping: LinkedHashMap<FirExpression, FirValueParameter>? = null
var numDefaults: Int = 0
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.inference.ConeTypeParameterBasedTypeVariable
import org.jetbrains.kotlin.fir.resolve.inference.InferenceComponents
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
@@ -95,7 +94,7 @@ class ConeOverloadConflictResolver(
}
if (discriminateSuspendConversions) {
val filtered = candidates.filterTo(mutableSetOf()) { !it.usesSuspendConversion }
val filtered = candidates.filterTo(mutableSetOf()) { !it.usesFunctionalConversion }
when (filtered.size) {
1 -> return filtered
0, candidates.size -> {
@@ -36,7 +36,7 @@ fun extractLambdaInfoFromFunctionalType(
duringCompletion
)
}
if (!expectedType.isSomeFunctionalType(session)) return null
val expectedFunctionalKind = expectedType.functionalTypeKind(session) ?: return null
val singleStatement = argument.body?.statements?.singleOrNull() as? FirReturnExpression
if (argument.returnType == null && singleStatement != null &&
@@ -100,7 +100,7 @@ fun extractLambdaInfoFromFunctionalType(
return ResolvedLambdaAtom(
argument,
expectedType,
expectedType.isSuspendOrKSuspendFunctionType(session),
expectedFunctionalKind,
receiverType,
contextReceivers,
parameters,
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.resolve.inference
import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.expressions.FirAnonymousFunctionExpression
@@ -21,6 +22,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind
import org.jetbrains.kotlin.types.model.typeConstructor
import org.jetbrains.kotlin.utils.addToStdlib.runIf
fun Candidate.preprocessLambdaArgument(
csBuilder: ConstraintSystemBuilder,
@@ -62,10 +64,10 @@ fun Candidate.preprocessLambdaArgument(
if (expectedType != null) {
val parameters = resolvedArgument.parameters
val lambdaType = createFunctionalType(
resolvedArgument.expectedFunctionalTypeKind ?: FunctionalTypeKind.Function,
if (resolvedArgument.coerceFirstParameterToExtensionReceiver) parameters.drop(1) else parameters,
resolvedArgument.receiver,
resolvedArgument.returnType,
isSuspend = resolvedArgument.isSuspend,
contextReceivers = resolvedArgument.contextReceivers,
)
@@ -105,18 +107,15 @@ private fun extractLambdaInfo(
session: FirSession,
candidate: Candidate?
): ResolvedLambdaAtom {
val isSuspend = expectedType?.isSuspendOrKSuspendFunctionType(session) ?: false
val isFunctionSupertype =
expectedType != null && expectedType.lowerBoundIfFlexible()
.isSomeFunctionalType(session)//isNotNullOrNullableFunctionSupertype(expectedType)
val expectedFunctionalKind = expectedType?.lowerBoundIfFlexible()?.functionalTypeKind(session)
val isFunctionSupertype = expectedFunctionalKind != null
val typeVariable = ConeTypeVariableForLambdaReturnType(argument, "_L")
val receiverType = argument.receiverType
val returnType =
argument.returnType
?: (expectedType?.typeArguments?.singleOrNull() as? ConeKotlinTypeProjection)?.type?.takeIf { isFunctionSupertype }
?: runIf(isFunctionSupertype) { (expectedType?.typeArguments?.singleOrNull() as? ConeKotlinTypeProjection)?.type }
?: typeVariable.defaultType
val nothingType = session.builtinTypes.nothingType.type
@@ -134,7 +133,7 @@ private fun extractLambdaInfo(
return ResolvedLambdaAtom(
argument,
expectedType,
isSuspend,
expectedFunctionalKind,
receiverType,
contextReceivers,
parameters,
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.resolve.inference
import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKind
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
@@ -39,7 +40,7 @@ sealed class PostponedResolvedAtom : PostponedResolvedAtomMarker {
class ResolvedLambdaAtom(
override val atom: FirAnonymousFunction,
expectedType: ConeKotlinType?,
val isSuspend: Boolean,
val expectedFunctionalTypeKind: FunctionalTypeKind?,
val receiver: ConeKotlinType?,
val contextReceivers: List<ConeKotlinType>,
val parameters: List<ConeKotlinType>,
@@ -570,12 +570,12 @@ class FirCallCompletionResultsWriterTransformer(
firRegularClass?.let answer@{
val functionType = samResolver.getFunctionTypeForPossibleSamType(firRegularClass.defaultType())
?: return@answer null
val kind = functionType.functionalTypeKind(session) ?: FunctionalTypeKind.Function
createFunctionalType(
kind,
functionType.typeArguments.dropLast(1).map { it as ConeKotlinType },
null,
functionType.typeArguments.last() as ConeKotlinType,
functionType.classId?.relativeClassName?.asString()
?.startsWith(FunctionalTypeKind.SuspendFunction.classNamePrefix) == true
functionType.typeArguments.last() as ConeKotlinType
)
}
}
@@ -617,8 +617,9 @@ class FirCallCompletionResultsWriterTransformer(
}
if (needUpdateLambdaType) {
val isSuspend = expectedType?.isSuspendOrKSuspendFunctionType(session) ?: result.isExplicitlySuspend(session)
result.replaceTypeRef(result.constructFunctionalTypeRef(isSuspend))
val kind = expectedType?.functionalTypeKind(session)
?: result.typeRef.coneTypeSafe<ConeClassLikeType>()?.functionalTypeKind(session)
result.replaceTypeRef(result.constructFunctionalTypeRef(kind))
session.lookupTracker?.recordTypeResolveAsLookup(result.typeRef, result.source, context.file.source)
}
// Have to delay this until the type is written to avoid adding a return if the type is Unit.
@@ -805,7 +805,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve
session.lookupTracker?.recordTypeResolveAsLookup(lambda.returnTypeRef, lambda.source, context.file.source)
}
lambda.replaceTypeRef(lambda.constructFunctionalTypeRef(resolvedLambdaAtom?.isSuspend == true))
lambda.replaceTypeRef(lambda.constructFunctionalTypeRef(resolvedLambdaAtom?.expectedFunctionalTypeKind))
session.lookupTracker?.recordTypeResolveAsLookup(lambda.typeRef, lambda.source, context.file.source)
lambda.addReturnToLastStatementIfNeeded()
return lambda
@@ -9,6 +9,8 @@ import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKind
import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKindExtractor
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.name.FqName
abstract class FirFunctionalTypeKindService : FirSessionComponent {
@@ -21,6 +23,9 @@ abstract class FirFunctionalTypeKindService : FirSessionComponent {
fun hasKindWithSpecificPackage(packageFqName: FqName): Boolean {
return extractor.hasKindWithSpecificPackage(packageFqName)
}
abstract fun extractSingleSpecialKindForFunction(functionSymbol: FirNamedFunctionSymbol): FunctionalTypeKind?
abstract fun extractAllSpecialKindsForFunction(functionSymbol: FirNamedFunctionSymbol): List<FunctionalTypeKind>
}
val FirSession.functionalTypeService: FirFunctionalTypeKindService by FirSession.sessionComponentAccessor()
@@ -5,6 +5,8 @@
package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKind
import org.jetbrains.kotlin.builtins.functions.isRegularFunction
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.resolve.calls.inference.model.*
@@ -28,7 +30,7 @@ class PostponedArgumentInputTypesResolver(
val parametersFromConstraints: Set<List<TypeWithKind>>?,
val annotations: List<AnnotationMarker>?,
val isExtensionFunction: Boolean,
val isSuspend: Boolean,
val functionalTypeKind: FunctionalTypeKind,
val isNullable: Boolean
)
@@ -94,14 +96,16 @@ class PostponedArgumentInputTypesResolver(
parameterTypesFromDeclaration,
)
var isSuspend = false
var functionalTypeKind: FunctionalTypeKind? = null
var isNullable = false
if (!functionalTypesFromConstraints.isNullOrEmpty()) {
if (functionalTypesFromConstraints.isNotEmpty()) {
isNullable = true
for (funType in functionalTypesFromConstraints) {
if (!isSuspend && funType.type.isSuspendFunctionTypeOrSubtype()) isSuspend = true
if (functionalTypeKind == null) {
funType.type.functionalTypeKind()?.takeUnless { it.isRegularFunction }?.let { functionalTypeKind = it }
}
if (isNullable && !funType.type.isMarkedNullable()) isNullable = false
if (isSuspend && !isNullable) break
if ((functionalTypeKind != null) && !isNullable) break
}
}
@@ -122,7 +126,7 @@ class PostponedArgumentInputTypesResolver(
parameterTypesFromConstraints,
annotations = annotations,
isExtensionFunction,
isSuspend = isSuspend,
functionalTypeKind ?: FunctionalTypeKind.Function,
isNullable = isNullable
)
}
@@ -254,7 +258,7 @@ class PostponedArgumentInputTypesResolver(
private fun Context.computeResultingFunctionalConstructor(
argument: PostponedAtomWithRevisableExpectedType,
parametersNumber: Int,
isSuspend: Boolean,
functionalTypeKind: FunctionalTypeKind,
resultTypeResolver: ResultTypeResolver
): TypeConstructorMarker {
val expectedType = argument.expectedType
@@ -264,7 +268,7 @@ class PostponedArgumentInputTypesResolver(
return when (argument) {
is LambdaWithTypeVariableAsExpectedTypeMarker ->
getFunctionTypeConstructor(parametersNumber, isSuspend)
getNonReflectFunctionTypeConstructor(parametersNumber, functionalTypeKind)
is PostponedCallableReferenceMarker -> {
val computedResultType = resultTypeResolver.findResultType(
this@computeResultingFunctionalConstructor,
@@ -276,7 +280,7 @@ class PostponedArgumentInputTypesResolver(
if (computedResultType.isBuiltinFunctionalTypeOrSubtype() && computedResultType.argumentsCount() > 1) {
computedResultType.typeConstructor()
} else {
getKFunctionTypeConstructor(parametersNumber, isSuspend)
getReflectFunctionTypeConstructor(parametersNumber, functionalTypeKind)
}
}
else -> throw IllegalStateException("Unsupported postponed argument type of $argument")
@@ -378,7 +382,7 @@ class PostponedArgumentInputTypesResolver(
val functionalConstructor = computeResultingFunctionalConstructor(
argument,
variablesForParameterTypes.size,
parameterTypesInfo.isSuspend,
parameterTypesInfo.functionalTypeKind,
resultTypeResolver
)
@@ -44,7 +44,7 @@ FILE fqName:<root> fileName:/adaptedExtensionFunctions.kt
FUN name:testExtensionVararg visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
CALL 'public final fun use (f: @[ExtensionFunctionType] kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
f: FUN_EXPR type=kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit> origin=ADAPTED_FUNCTION_REFERENCE
f: FUN_EXPR type=@[ExtensionFunctionType] kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:extensionVararg visibility:local modality:FINAL <> (p0:<root>.C, p1:kotlin.Int) returnType:kotlin.Unit
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:<root>.C
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p1 index:1 type:kotlin.Int
@@ -55,7 +55,7 @@ FILE fqName:<root> fileName:/adaptedExtensionFunctions.kt
FUN name:testExtensionDefault visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
CALL 'public final fun use (f: @[ExtensionFunctionType] kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
f: FUN_EXPR type=kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit> origin=ADAPTED_FUNCTION_REFERENCE
f: FUN_EXPR type=@[ExtensionFunctionType] kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:extensionDefault visibility:local modality:FINAL <> (p0:<root>.C, p1:kotlin.Int) returnType:kotlin.Unit
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:<root>.C
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p1 index:1 type:kotlin.Int
@@ -66,7 +66,7 @@ FILE fqName:<root> fileName:/adaptedExtensionFunctions.kt
FUN name:testExtensionBoth visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
CALL 'public final fun use (f: @[ExtensionFunctionType] kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
f: FUN_EXPR type=kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit> origin=ADAPTED_FUNCTION_REFERENCE
f: FUN_EXPR type=@[ExtensionFunctionType] kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:extensionBoth visibility:local modality:FINAL <> (p0:<root>.C, p1:kotlin.Int) returnType:kotlin.Unit
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:<root>.C
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p1 index:1 type:kotlin.Int
@@ -47,7 +47,7 @@ FILE fqName:<root> fileName:/cannotCastToFunction.kt
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'dumpStrategy: kotlin.String declared in <root>.dump' type=kotlin.String origin=null
arg1: CONST String type=kotlin.String value="KotlinLike"
then: FUN_EXPR type=kotlin.Function1<<root>.IrElement, kotlin.String> origin=ADAPTED_FUNCTION_REFERENCE
then: FUN_EXPR type=@[ExtensionFunctionType] kotlin.Function1<<root>.IrElement, kotlin.String> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:dumpKotlinLike visibility:local modality:FINAL <> (p0:<root>.IrElement) returnType:kotlin.String
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:<root>.IrElement
BLOCK_BODY
@@ -56,7 +56,7 @@ FILE fqName:<root> fileName:/cannotCastToFunction.kt
$receiver: GET_VAR 'p0: <root>.IrElement declared in <root>.dump.dumpKotlinLike' type=<root>.IrElement origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: FUN_EXPR type=kotlin.Function1<<root>.IrElement, kotlin.String> origin=ADAPTED_FUNCTION_REFERENCE
then: FUN_EXPR type=@[ExtensionFunctionType] kotlin.Function1<<root>.IrElement, kotlin.String> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:dump visibility:local modality:FINAL <> (p0:<root>.IrElement) returnType:kotlin.String
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:<root>.IrElement
BLOCK_BODY
@@ -85,6 +85,8 @@ abstract class FunctionalTypeKind internal constructor(
fun numberedClassName(arity: Int): Name = Name.identifier("$classNamePrefix$arity")
fun numberedClassId(arity: Int): ClassId = ClassId(packageFqName, numberedClassName(arity))
override fun toString(): String {
return "$packageFqName.${classNamePrefix}N"
}
@@ -141,5 +143,7 @@ val FunctionalTypeKind.isBuiltin: Boolean
}
val FunctionalTypeKind.isSuspendType: Boolean
get() = this == FunctionalTypeKind.SuspendFunction || this == FunctionalTypeKind.KSuspendFunction
get() = this.nonReflectKind() == FunctionalTypeKind.SuspendFunction
val FunctionalTypeKind.isRegularFunction: Boolean
get() = this.nonReflectKind() == FunctionalTypeKind.Function
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.types.model
import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKind
import org.jetbrains.kotlin.resolve.checkers.EmptyIntersectionTypeChecker
import org.jetbrains.kotlin.resolve.checkers.EmptyIntersectionTypeInfo
import org.jetbrains.kotlin.types.*
@@ -247,9 +248,11 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
fun KotlinTypeMarker.isSignedOrUnsignedNumberType(): Boolean
// ------------- functional type utils -------------
fun KotlinTypeMarker.isFunctionOrKFunctionWithAnySuspendability(): Boolean
fun KotlinTypeMarker.isSuspendFunctionTypeOrSubtype(): Boolean
fun KotlinTypeMarker.functionalTypeKind(): FunctionalTypeKind?
fun KotlinTypeMarker.isExtensionFunctionType(): Boolean
@@ -257,12 +260,14 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
fun KotlinTypeMarker.getFunctionalTypeFromSupertypes(): KotlinTypeMarker
fun getNonReflectFunctionTypeConstructor(parametersNumber: Int, kind: FunctionalTypeKind): TypeConstructorMarker
fun getReflectFunctionTypeConstructor(parametersNumber: Int, kind: FunctionalTypeKind): TypeConstructorMarker
// -------------------------------------------------
fun StubTypeMarker.getOriginalTypeVariable(): TypeVariableTypeConstructorMarker
fun getFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker
fun getKFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker
private fun <T> KotlinTypeMarker.extractTypeOf(to: MutableSet<T>, getIfApplicable: (TypeConstructorMarker) -> T?) {
for (i in 0 until argumentsCount()) {
val argument = getArgument(i)
@@ -59,17 +59,20 @@ val KotlinType.isBuiltinFunctionalTypeOrSubtype: Boolean
fun KotlinType.isFunctionTypeOrSubtype(predicate: (KotlinType) -> Boolean): Boolean =
isTypeOrSubtypeOf { it.isFunctionType && predicate(it) }
val KotlinType.functionalTypeKind: FunctionalTypeKind?
get() = constructor.declarationDescriptor?.getFunctionalClassKind()
val KotlinType.isFunctionType: Boolean
get() = constructor.declarationDescriptor?.getFunctionalClassKind() == FunctionalTypeKind.Function
get() = functionalTypeKind == FunctionalTypeKind.Function
val KotlinType.isKFunctionType: Boolean
get() = constructor.declarationDescriptor?.getFunctionalClassKind() == FunctionalTypeKind.KFunction
get() = functionalTypeKind == FunctionalTypeKind.KFunction
val KotlinType.isSuspendFunctionType: Boolean
get() = constructor.declarationDescriptor?.getFunctionalClassKind() == FunctionalTypeKind.SuspendFunction
get() = functionalTypeKind == FunctionalTypeKind.SuspendFunction
val KotlinType.isKSuspendFunctionType: Boolean
get() = constructor.declarationDescriptor?.getFunctionalClassKind() == FunctionalTypeKind.KSuspendFunction
get() = functionalTypeKind == FunctionalTypeKind.KSuspendFunction
val KotlinType.isFunctionOrSuspendFunctionType: Boolean
get() = isFunctionType || isSuspendFunctionType
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.types.checker
import org.jetbrains.kotlin.builtins.*
import org.jetbrains.kotlin.builtins.StandardNames.FqNames
import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKind
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -849,11 +850,6 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
return this.isFunctionOrKFunctionTypeWithAnySuspendability
}
override fun KotlinTypeMarker.isSuspendFunctionTypeOrSubtype(): Boolean {
require(this is KotlinType, this::errorMessage)
return this.isSuspendFunctionTypeOrSubtype
}
override fun KotlinTypeMarker.isExtensionFunctionType(): Boolean {
require(this is KotlinType, this::errorMessage)
return this.isBuiltinExtensionFunctionalType
@@ -869,12 +865,25 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
return this.extractFunctionalTypeFromSupertypes()
}
override fun getFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker {
return getFunctionDescriptor(builtIns, parametersNumber, isSuspend).typeConstructor
override fun KotlinTypeMarker.functionalTypeKind(): FunctionalTypeKind? {
require(this is KotlinType)
return this.functionalTypeKind
}
override fun getKFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker {
return getKFunctionDescriptor(builtIns, parametersNumber, isSuspend).typeConstructor
override fun getNonReflectFunctionTypeConstructor(parametersNumber: Int, kind: FunctionalTypeKind): TypeConstructorMarker {
return getFunctionDescriptor(
builtIns,
parametersNumber,
isSuspendFunction = kind.nonReflectKind() == FunctionalTypeKind.SuspendFunction
).typeConstructor
}
override fun getReflectFunctionTypeConstructor(parametersNumber: Int, kind: FunctionalTypeKind): TypeConstructorMarker {
return getKFunctionDescriptor(
builtIns,
parametersNumber,
isSuspendFunction = kind.reflectKind() == FunctionalTypeKind.KSuspendFunction
).typeConstructor
}
override fun createSubstitutorForSuperTypes(baseType: KotlinTypeMarker): TypeSubstitutorMarker? {
@@ -5,15 +5,16 @@
package org.jetbrains.kotlin.samWithReceiver.k2
import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
import org.jetbrains.kotlin.fir.resolve.FirSamConversionTransformerExtension
import org.jetbrains.kotlin.fir.resolve.createFunctionalType
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.functionalTypeService
import org.jetbrains.kotlin.utils.addToStdlib.runIf
class FirSamWithReceiverConventionTransformer(
@@ -25,11 +26,12 @@ class FirSamWithReceiverConventionTransformer(
return runIf(containingClassSymbol.resolvedAnnotationClassIds.any { it.asSingleFqName().asString() in annotations }) {
val parameterTypes = function.valueParameters.map { it.returnTypeRef.coneType }
if (parameterTypes.isEmpty()) return null
val kind = session.functionalTypeService.extractSingleSpecialKindForFunction(function.symbol) ?: FunctionalTypeKind.Function
createFunctionalType(
kind,
parameters = parameterTypes.subList(1, parameterTypes.size),
receiverType = parameterTypes[0],
rawReturnType = function.returnTypeRef.coneType,
isSuspend = function.isSuspend
rawReturnType = function.returnTypeRef.coneType
)
}
}
@@ -8,6 +8,7 @@
package org.jetbrains.kotlin.scripting.compiler.plugin.impl
import com.intellij.openapi.Disposable
import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKind
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments
@@ -41,7 +42,6 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.builder.scriptConfigurators
import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.extensions.extensionService
import org.jetbrains.kotlin.fir.resolve.FirSamConversionTransformerExtension
@@ -49,6 +49,7 @@ import org.jetbrains.kotlin.fir.resolve.createFunctionalType
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.functionalTypeService
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.psi.KtFile
@@ -158,11 +159,12 @@ internal class FirScriptingSamWithReceiverExtensionRegistrar() : FirExtensionReg
return runIf(containingClassSymbol.resolvedAnnotationClassIds.any { it.asSingleFqName().asString() in knownAnnotations }) {
val parameterTypes = function.valueParameters.map { it.returnTypeRef.coneType }
if (parameterTypes.isEmpty()) return null
val kind = session.functionalTypeService.extractSingleSpecialKindForFunction(function.symbol) ?: FunctionalTypeKind.Function
createFunctionalType(
kind,
parameters = parameterTypes.subList(1, parameterTypes.size),
receiverType = parameterTypes[0],
rawReturnType = function.returnTypeRef.coneType,
isSuspend = function.isSuspend
rawReturnType = function.returnTypeRef.coneType
)
}
}