FIR: extend suspend conversion to intersection type
This commit is contained in:
committed by
TeamCityServer
parent
42ea4463ee
commit
2dfba10d84
+11
-16
@@ -400,8 +400,8 @@ internal class AdapterGenerator(
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
val expectedType = parameter?.returnTypeRef?.coneType ?: return this
|
val expectedType = parameter?.returnTypeRef?.coneType ?: return this
|
||||||
// Expect the expected type to be a suspend functional type, and the argument type is not a suspend functional type.
|
// Expect the expected type to be a suspend functional type.
|
||||||
if (!expectedType.isSuspendFunctionType(session) || argument.typeRef.coneType.isSuspendFunctionType(session)) {
|
if (!expectedType.isSuspendFunctionType(session)) {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
val expectedFunctionalType = expectedType.suspendFunctionTypeToFunctionType(session)
|
val expectedFunctionalType = expectedType.suspendFunctionTypeToFunctionType(session)
|
||||||
@@ -424,22 +424,17 @@ internal class AdapterGenerator(
|
|||||||
|
|
||||||
private fun findInvokeSymbol(expectedFunctionalType: ConeClassLikeType, argument: FirExpression): IrSimpleFunctionSymbol? {
|
private fun findInvokeSymbol(expectedFunctionalType: ConeClassLikeType, argument: FirExpression): IrSimpleFunctionSymbol? {
|
||||||
val argumentType = argument.typeRef.coneType
|
val argumentType = argument.typeRef.coneType
|
||||||
// To avoid any remaining exotic types, e.g., intersection type, like it(FunctionN..., SuspendFunctionN...)
|
val argumentTypeWithInvoke = argumentType.findSubtypeOfNonSuspendFunctionalType(session, expectedFunctionalType) ?: return null
|
||||||
if (argumentType !is ConeClassLikeType) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argumentType.isSubtypeOfFunctionalType(session, expectedFunctionalType)) {
|
return if (argumentTypeWithInvoke.isBuiltinFunctionalType(session)) {
|
||||||
return if (argumentType.isBuiltinFunctionalType(session)) {
|
(argumentTypeWithInvoke as? ConeClassLikeType)?.findBaseInvokeSymbol(session, scopeSession)
|
||||||
argumentType.findBaseInvokeSymbol(session, scopeSession)
|
} else {
|
||||||
} else {
|
argumentTypeWithInvoke.findContributedInvokeSymbol(
|
||||||
argumentType.findContributedInvokeSymbol(session, scopeSession, expectedFunctionalType, shouldCalculateReturnTypesOfFakeOverrides = true)
|
session, scopeSession, expectedFunctionalType, shouldCalculateReturnTypesOfFakeOverrides = true
|
||||||
}?.let {
|
)
|
||||||
declarationStorage.getIrFunctionSymbol(it) as? IrSimpleFunctionSymbol
|
}?.let {
|
||||||
}
|
declarationStorage.getIrFunctionSymbol(it) as? IrSimpleFunctionSymbol
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createAdapterFunctionForArgument(
|
private fun createAdapterFunctionForArgument(
|
||||||
|
|||||||
@@ -247,36 +247,30 @@ private fun argumentTypeWithSuspendConversion(
|
|||||||
): ConeKotlinType? {
|
): ConeKotlinType? {
|
||||||
// TODO: should refer to LanguageVersionSettings.SuspendConversion
|
// TODO: should refer to LanguageVersionSettings.SuspendConversion
|
||||||
|
|
||||||
// To avoid any remaining exotic types, e.g., intersection type, like it(FunctionN..., SuspendFunctionN...)
|
// Expect the expected type to be a suspend functional type.
|
||||||
if (argumentType !is ConeClassLikeType) {
|
if (!expectedType.isSuspendFunctionType(session)) {
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expect the expected type to be a suspend functional type, and the argument type is not a suspend functional type.
|
|
||||||
if (!expectedType.isSuspendFunctionType(session) || argumentType.isSuspendFunctionType(session)) {
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to check the argument type against non-suspend functional type.
|
// We want to check the argument type against non-suspend functional type.
|
||||||
val expectedFunctionalType = expectedType.suspendFunctionTypeToFunctionType(session)
|
val expectedFunctionalType = expectedType.suspendFunctionTypeToFunctionType(session)
|
||||||
if (argumentType.isSubtypeOfFunctionalType(session, expectedFunctionalType)) {
|
|
||||||
return argumentType.findContributedInvokeSymbol(
|
|
||||||
session,
|
|
||||||
scopeSession,
|
|
||||||
expectedFunctionalType,
|
|
||||||
shouldCalculateReturnTypesOfFakeOverrides = false
|
|
||||||
)?.let { invokeSymbol ->
|
|
||||||
createFunctionalType(
|
|
||||||
invokeSymbol.fir.valueParameters.map { it.returnTypeRef.coneType },
|
|
||||||
null,
|
|
||||||
invokeSymbol.fir.returnTypeRef.coneType,
|
|
||||||
isSuspend = true,
|
|
||||||
isKFunctionType = argumentType.isKFunctionType(session)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
val argumentTypeWithInvoke = argumentType.findSubtypeOfNonSuspendFunctionalType(session, expectedFunctionalType)
|
||||||
|
|
||||||
|
return argumentTypeWithInvoke?.findContributedInvokeSymbol(
|
||||||
|
session,
|
||||||
|
scopeSession,
|
||||||
|
expectedFunctionalType,
|
||||||
|
shouldCalculateReturnTypesOfFakeOverrides = false
|
||||||
|
)?.let { invokeSymbol ->
|
||||||
|
createFunctionalType(
|
||||||
|
invokeSymbol.fir.valueParameters.map { it.returnTypeRef.coneType },
|
||||||
|
null,
|
||||||
|
invokeSymbol.fir.returnTypeRef.coneType,
|
||||||
|
isSuspend = true,
|
||||||
|
isKFunctionType = argumentType.isKFunctionType(session)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Candidate.prepareCapturedType(argumentType: ConeKotlinType, context: ResolutionContext): ConeKotlinType {
|
fun Candidate.prepareCapturedType(argumentType: ConeKotlinType, context: ResolutionContext): ConeKotlinType {
|
||||||
|
|||||||
@@ -97,6 +97,33 @@ fun ConeKotlinType.isSubtypeOfFunctionalType(session: FirSession, expectedFuncti
|
|||||||
return AbstractTypeChecker.isSubtypeOf(session.typeContext, this, expectedFunctionalType.replaceArgumentsWithStarProjections())
|
return AbstractTypeChecker.isSubtypeOf(session.typeContext, this, expectedFunctionalType.replaceArgumentsWithStarProjections())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ConeKotlinType.findSubtypeOfNonSuspendFunctionalType(session: FirSession, expectedFunctionalType: ConeClassLikeType): ConeKotlinType? {
|
||||||
|
require(expectedFunctionalType.isBuiltinFunctionalType(session) && !expectedFunctionalType.isSuspendFunctionType(session))
|
||||||
|
return when (this) {
|
||||||
|
is ConeClassLikeType -> {
|
||||||
|
// Expect the argument type is not a suspend functional type.
|
||||||
|
if (isSuspendFunctionType(session) || !isSubtypeOfFunctionalType(session, expectedFunctionalType))
|
||||||
|
null
|
||||||
|
else
|
||||||
|
this
|
||||||
|
}
|
||||||
|
is ConeIntersectionType -> {
|
||||||
|
if (intersectedTypes.any { it.isSuspendFunctionType(session) })
|
||||||
|
null
|
||||||
|
else
|
||||||
|
intersectedTypes.find { it.findSubtypeOfNonSuspendFunctionalType(session, expectedFunctionalType) != null }
|
||||||
|
}
|
||||||
|
is ConeTypeParameterType -> {
|
||||||
|
val bounds = lookupTag.typeParameterSymbol.fir.bounds.map { it.coneType }
|
||||||
|
if (bounds.any { it.isSuspendFunctionType(session) })
|
||||||
|
null
|
||||||
|
else
|
||||||
|
bounds.find { it.findSubtypeOfNonSuspendFunctionalType(session, expectedFunctionalType) != null }
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun ConeClassLikeType.findBaseInvokeSymbol(session: FirSession, scopeSession: ScopeSession): FirFunctionSymbol<*>? {
|
fun ConeClassLikeType.findBaseInvokeSymbol(session: FirSession, scopeSession: ScopeSession): FirFunctionSymbol<*>? {
|
||||||
require(this.isBuiltinFunctionalType(session))
|
require(this.isBuiltinFunctionalType(session))
|
||||||
val functionN = (lookupTag.toSymbol(session)?.fir as? FirClass<*>) ?: return null
|
val functionN = (lookupTag.toSymbol(session)?.fir as? FirClass<*>) ?: return null
|
||||||
|
|||||||
Vendored
-1
@@ -3,7 +3,6 @@
|
|||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// IGNORE_BACKEND: JVM, NATIVE, JS, JS_IR
|
// IGNORE_BACKEND: JVM, NATIVE, JS, JS_IR
|
||||||
// IGNORE_BACKEND: JS_IR_ES6
|
// IGNORE_BACKEND: JS_IR_ES6
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// IGNORE_LIGHT_ANALYSIS
|
// IGNORE_LIGHT_ANALYSIS
|
||||||
|
|
||||||
import helpers.*
|
import helpers.*
|
||||||
|
|||||||
Reference in New Issue
Block a user