[FIR] Generify resolution and inference of arguments of functional types
This commit is contained in:
committed by
Space Team
parent
67aa80562d
commit
d1b797ed97
+1
-2
@@ -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)
|
||||
|
||||
+2
-1
@@ -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(
|
||||
|
||||
+30
@@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+32
-13
@@ -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
|
||||
|
||||
+1
-2
@@ -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 -> {
|
||||
|
||||
+2
-2
@@ -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,
|
||||
|
||||
+7
-8
@@ -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,
|
||||
|
||||
+2
-1
@@ -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>,
|
||||
|
||||
+6
-5
@@ -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.
|
||||
|
||||
+1
-1
@@ -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()
|
||||
|
||||
+14
-10
@@ -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
|
||||
)
|
||||
|
||||
|
||||
Vendored
+3
-3
@@ -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
|
||||
|
||||
+5
-1
@@ -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
|
||||
|
||||
+18
-9
@@ -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
-3
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+5
-3
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user