FIR2IR: properly support combinations of SAM/suspend conversions
This commit is contained in:
committed by
TeamCityServer
parent
e574d3be27
commit
9b42fab9de
+15
-12
@@ -414,12 +414,10 @@ internal class AdapterGenerator(
|
|||||||
if (!needSamConversion(argument, parameter)) {
|
if (!needSamConversion(argument, parameter)) {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
val samFirType = parameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()?.let {
|
val parameterType = parameter.returnTypeRef.coneType
|
||||||
var substituted = substitutor.substituteOrSelf(it)
|
val substitutedParameterType = starProjectionApproximator.substituteOrSelf(substitutor.substituteOrSelf(parameterType))
|
||||||
substituted = starProjectionApproximator.substituteOrSelf(substituted)
|
val samFirType = if (substitutedParameterType is ConeRawType) substitutedParameterType.lowerBound else substitutedParameterType
|
||||||
if (substituted is ConeRawType) substituted.lowerBound else substituted
|
var samType = samFirType.toIrType(ConversionTypeContext.WITH_INVARIANT)
|
||||||
}
|
|
||||||
var samType = samFirType?.toIrType(ConversionTypeContext.WITH_INVARIANT) ?: createErrorType()
|
|
||||||
if (shouldUnwrapVarargType) {
|
if (shouldUnwrapVarargType) {
|
||||||
samType = samType.getArrayElementType(irBuiltIns)
|
samType = samType.getArrayElementType(irBuiltIns)
|
||||||
}
|
}
|
||||||
@@ -448,10 +446,14 @@ internal class AdapterGenerator(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// On the other hand, the actual type should be either a functional type or a subtype of a class that has a contributed `invoke`.
|
// On the other hand, the actual type should be either a functional type or a subtype of a class that has a contributed `invoke`.
|
||||||
val expectedFunctionType = samResolver.getFunctionTypeForPossibleSamType(parameter.returnTypeRef.coneType)
|
val expectedFunctionType = getFunctionTypeForPossibleSamType(parameter.returnTypeRef.coneType)
|
||||||
return argument.isFunctional(session, scopeSession, expectedFunctionType)
|
return argument.isFunctional(session, scopeSession, expectedFunctionType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun getFunctionTypeForPossibleSamType(parameterType: ConeKotlinType): ConeKotlinType? {
|
||||||
|
return samResolver.getFunctionTypeForPossibleSamType(parameterType)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For example,
|
* For example,
|
||||||
* fun consumer(f: suspend () -> Unit) = ...
|
* fun consumer(f: suspend () -> Unit) = ...
|
||||||
@@ -468,21 +470,22 @@ internal class AdapterGenerator(
|
|||||||
*/
|
*/
|
||||||
internal fun IrExpression.applySuspendConversionIfNeeded(
|
internal fun IrExpression.applySuspendConversionIfNeeded(
|
||||||
argument: FirExpression,
|
argument: FirExpression,
|
||||||
parameter: FirValueParameter?
|
parameterType: ConeKotlinType,
|
||||||
|
samFunctionType: ConeKotlinType?
|
||||||
): IrExpression {
|
): IrExpression {
|
||||||
// TODO: should refer to LanguageVersionSettings.SuspendConversion
|
// TODO: should refer to LanguageVersionSettings.SuspendConversion
|
||||||
if (this is IrBlock && origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE) {
|
if (this is IrBlock && origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE) {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
val expectedType = parameter?.returnTypeRef?.coneType ?: return this
|
|
||||||
// Expect the expected type to be a suspend functional type.
|
// Expect the expected type to be a suspend functional type.
|
||||||
if (!expectedType.isSuspendFunctionType(session)) {
|
val potentialFunctionType = samFunctionType ?: parameterType
|
||||||
|
if (!potentialFunctionType.isSuspendFunctionType(session)) {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
val expectedFunctionalType = expectedType.suspendFunctionTypeToFunctionType(session)
|
val expectedFunctionalType = potentialFunctionType.suspendFunctionTypeToFunctionType(session)
|
||||||
|
|
||||||
val invokeSymbol = findInvokeSymbol(expectedFunctionalType, argument) ?: return this
|
val invokeSymbol = findInvokeSymbol(expectedFunctionalType, argument) ?: return this
|
||||||
val suspendConvertedType = expectedType.toIrType() as IrSimpleType
|
val suspendConvertedType = potentialFunctionType.toIrType() as IrSimpleType
|
||||||
return argument.convertWithOffsets { startOffset, endOffset ->
|
return argument.convertWithOffsets { startOffset, endOffset ->
|
||||||
val irAdapterFunction = createAdapterFunctionForArgument(startOffset, endOffset, suspendConvertedType, type, invokeSymbol)
|
val irAdapterFunction = createAdapterFunctionForArgument(startOffset, endOffset, suspendConvertedType, type, invokeSymbol)
|
||||||
// TODO add a bound receiver property to IrFunctionExpressionImpl?
|
// TODO add a bound receiver property to IrFunctionExpressionImpl?
|
||||||
|
|||||||
+3
-1
@@ -657,7 +657,9 @@ class CallAndReferenceGenerator(
|
|||||||
with(adapterGenerator) {
|
with(adapterGenerator) {
|
||||||
if (parameter?.returnTypeRef is FirResolvedTypeRef) {
|
if (parameter?.returnTypeRef is FirResolvedTypeRef) {
|
||||||
// Java type case (from annotations)
|
// Java type case (from annotations)
|
||||||
irArgument = irArgument.applySuspendConversionIfNeeded(argument, parameter)
|
val parameterType = parameter.returnTypeRef.coneType
|
||||||
|
val samFunctionType = getFunctionTypeForPossibleSamType(parameterType)
|
||||||
|
irArgument = irArgument.applySuspendConversionIfNeeded(argument, parameterType, samFunctionType)
|
||||||
irArgument = irArgument.applySamConversionIfNeeded(argument, parameter, substitutor)
|
irArgument = irArgument.applySamConversionIfNeeded(argument, parameter, substitutor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
-2
@@ -1,7 +1,5 @@
|
|||||||
// !LANGUAGE: +SuspendConversion
|
// !LANGUAGE: +SuspendConversion
|
||||||
// IGNORE_BACKEND: JVM
|
// IGNORE_BACKEND: JVM
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// FIR status: ChainedFunSuspendConversionForSimpleExpressionKt$box$1 cannot be cast to kotlin.jvm.functions.Function1
|
|
||||||
|
|
||||||
fun interface SuspendRunnable {
|
fun interface SuspendRunnable {
|
||||||
suspend fun invoke()
|
suspend fun invoke()
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// !LANGUAGE: +SuspendConversion
|
// !LANGUAGE: +SuspendConversion
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
// IGNORE_BACKEND: JVM
|
// IGNORE_BACKEND: JVM
|
||||||
|
|||||||
-2
@@ -1,8 +1,6 @@
|
|||||||
// !LANGUAGE: +SuspendConversion
|
// !LANGUAGE: +SuspendConversion
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
|
||||||
// IGNORE_BACKEND: JVM
|
// IGNORE_BACKEND: JVM
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// FIR status: SuspendAndFunConversionInDisabledModeKt$box$1 cannot be cast to kotlin.jvm.functions.Function1
|
|
||||||
|
|
||||||
fun interface Runnable {
|
fun interface Runnable {
|
||||||
fun run()
|
fun run()
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// !LANGUAGE: +SuspendConversion
|
// !LANGUAGE: +SuspendConversion
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
// IGNORE_BACKEND: JVM
|
// IGNORE_BACKEND: JVM
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// !LANGUAGE: +SuspendConversion
|
// !LANGUAGE: +SuspendConversion
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
// IGNORE_BACKEND: JVM
|
// IGNORE_BACKEND: JVM
|
||||||
|
|||||||
Vendored
-1
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// !LANGUAGE: +SuspendConversion
|
// !LANGUAGE: +SuspendConversion
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
|||||||
Vendored
+24
-3
@@ -32,12 +32,33 @@ FILE fqName:<root> fileName:/chainedFunSuspendConversionForSimpleExpression.kt
|
|||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CALL 'public final fun foo (s: <root>.SuspendRunnable): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
CALL 'public final fun foo (s: <root>.SuspendRunnable): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
s: TYPE_OP type=<root>.SuspendRunnable origin=SAM_CONVERSION typeOperand=<root>.SuspendRunnable
|
s: TYPE_OP type=<root>.SuspendRunnable origin=SAM_CONVERSION typeOperand=<root>.SuspendRunnable
|
||||||
GET_VAR 'f: kotlin.Function0<kotlin.Unit> declared in <root>.test' type=kotlin.Function0<kotlin.Unit> origin=null
|
BLOCK type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=SUSPEND_CONVERSION
|
||||||
|
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> ($receiver:kotlin.Function0<kotlin.Unit>) returnType:kotlin.Unit [suspend]
|
||||||
|
$receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:callee type:kotlin.Function0<kotlin.Unit>
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=null
|
||||||
|
$this: GET_VAR 'callee: kotlin.Function0<kotlin.Unit> declared in <root>.test.suspendConversion' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
|
FUNCTION_REFERENCE 'local final fun suspendConversion (): kotlin.Unit [suspend] declared in <root>.test' type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=SUSPEND_CONVERSION reflectionTarget=null
|
||||||
|
$receiver: GET_VAR 'f: kotlin.Function0<kotlin.Unit> declared in <root>.test' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
CALL 'public final fun foo (s: <root>.SuspendRunnable): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
CALL 'public final fun foo (s: <root>.SuspendRunnable): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
s: TYPE_OP type=<root>.SuspendRunnable origin=SAM_CONVERSION typeOperand=<root>.SuspendRunnable
|
s: TYPE_OP type=<root>.SuspendRunnable origin=SAM_CONVERSION typeOperand=<root>.SuspendRunnable
|
||||||
CALL 'public final fun bar (): kotlin.Function0<kotlin.Unit> declared in <root>' type=kotlin.Function0<kotlin.Unit> origin=null
|
BLOCK type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=SUSPEND_CONVERSION
|
||||||
|
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> ($receiver:kotlin.Function0<kotlin.Unit>) returnType:kotlin.Unit [suspend]
|
||||||
|
$receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:callee type:kotlin.Function0<kotlin.Unit>
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=null
|
||||||
|
$this: GET_VAR 'callee: kotlin.Function0<kotlin.Unit> declared in <root>.test.suspendConversion' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
|
FUNCTION_REFERENCE 'local final fun suspendConversion (): kotlin.Unit [suspend] declared in <root>.test' type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=SUSPEND_CONVERSION reflectionTarget=null
|
||||||
|
$receiver: CALL 'public final fun bar (): kotlin.Function0<kotlin.Unit> declared in <root>' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
VAR name:t type:kotlin.Function0<kotlin.Unit> [var]
|
VAR name:t type:kotlin.Function0<kotlin.Unit> [var]
|
||||||
GET_VAR 'f: kotlin.Function0<kotlin.Unit> declared in <root>.test' type=kotlin.Function0<kotlin.Unit> origin=null
|
GET_VAR 'f: kotlin.Function0<kotlin.Unit> declared in <root>.test' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
CALL 'public final fun foo (s: <root>.SuspendRunnable): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
CALL 'public final fun foo (s: <root>.SuspendRunnable): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
s: TYPE_OP type=<root>.SuspendRunnable origin=SAM_CONVERSION typeOperand=<root>.SuspendRunnable
|
s: TYPE_OP type=<root>.SuspendRunnable origin=SAM_CONVERSION typeOperand=<root>.SuspendRunnable
|
||||||
GET_VAR 'var t: kotlin.Function0<kotlin.Unit> [var] declared in <root>.test' type=kotlin.Function0<kotlin.Unit> origin=null
|
BLOCK type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=SUSPEND_CONVERSION
|
||||||
|
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> ($receiver:kotlin.Function0<kotlin.Unit>) returnType:kotlin.Unit [suspend]
|
||||||
|
$receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:callee type:kotlin.Function0<kotlin.Unit>
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=null
|
||||||
|
$this: GET_VAR 'callee: kotlin.Function0<kotlin.Unit> declared in <root>.test.suspendConversion' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
|
FUNCTION_REFERENCE 'local final fun suspendConversion (): kotlin.Unit [suspend] declared in <root>.test' type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=SUSPEND_CONVERSION reflectionTarget=null
|
||||||
|
$receiver: GET_VAR 'var t: kotlin.Function0<kotlin.Unit> [var] declared in <root>.test' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
|
|||||||
Reference in New Issue
Block a user