[FIR2IR] Fix cast insertion in SAM conversion with suspend conversion
#KT-65878 #KT-62855
This commit is contained in:
committed by
Space Team
parent
a2a217799b
commit
b054a4481d
+11
-2
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.backend.generators
|
package org.jetbrains.kotlin.fir.backend.generators
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.functions.isSuspendOrKSuspendFunction
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.fir.backend.*
|
import org.jetbrains.kotlin.fir.backend.*
|
||||||
@@ -423,7 +424,7 @@ internal class AdapterGenerator(
|
|||||||
castArgumentToFunctionalInterfaceForSamType(this, firSamConversion.expression.resolvedType, samFirType)
|
castArgumentToFunctionalInterfaceForSamType(this, firSamConversion.expression.resolvedType, samFirType)
|
||||||
)
|
)
|
||||||
|
|
||||||
return if (this is IrBlock && origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE) {
|
return if (this is IrBlock && (origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE || origin == IrStatementOrigin.SUSPEND_CONVERSION)) {
|
||||||
// The IR for adapted callable references should be
|
// The IR for adapted callable references should be
|
||||||
// BLOCK ADAPTED_FUNCTION_REFERENCE(FUN ADAPTER_FOR_CALLABLE_REFERENCE, TYPE_OP SAM_CONVERSION(FUNCTION_REFERENCE))
|
// BLOCK ADAPTED_FUNCTION_REFERENCE(FUN ADAPTER_FOR_CALLABLE_REFERENCE, TYPE_OP SAM_CONVERSION(FUNCTION_REFERENCE))
|
||||||
// Therefore, we need to insert the cast as the last statement of the block, not around the block itself.
|
// Therefore, we need to insert the cast as the last statement of the block, not around the block itself.
|
||||||
@@ -445,13 +446,21 @@ internal class AdapterGenerator(
|
|||||||
): IrExpression {
|
): IrExpression {
|
||||||
// The rule for SAM conversions is: the argument must be a subtype of the required function type.
|
// The rule for SAM conversions is: the argument must be a subtype of the required function type.
|
||||||
// We handle intersection types, captured types, etc. by approximating both expected and actual types.
|
// We handle intersection types, captured types, etc. by approximating both expected and actual types.
|
||||||
val approximatedConeKotlinFunctionType = getFunctionTypeForPossibleSamType(samType)?.approximateForIrOrSelf() ?: return argument
|
var approximatedConeKotlinFunctionType = getFunctionTypeForPossibleSamType(samType)?.approximateForIrOrSelf() ?: return argument
|
||||||
|
|
||||||
// This line is not present in the K1 counterpart because there is InsertImplicitCasts::cast that effectively removes
|
// This line is not present in the K1 counterpart because there is InsertImplicitCasts::cast that effectively removes
|
||||||
// such unnecessary casts. At the same time, many IR lowerings assume that there are no such redundant casts and many
|
// such unnecessary casts. At the same time, many IR lowerings assume that there are no such redundant casts and many
|
||||||
// tests from FirBlackBoxCodegenTestGenerated relevant to INDY start failing once this line is removed.
|
// tests from FirBlackBoxCodegenTestGenerated relevant to INDY start failing once this line is removed.
|
||||||
val approximateArgumentConeType = argumentConeType.approximateForIrOrSelf()
|
val approximateArgumentConeType = argumentConeType.approximateForIrOrSelf()
|
||||||
|
|
||||||
|
// We don't want to insert a redundant cast from a function type to a suspend function type,
|
||||||
|
// because that's already handled by suspend conversion.
|
||||||
|
if (approximatedConeKotlinFunctionType.functionTypeKind(session)?.isSuspendOrKSuspendFunction == true &&
|
||||||
|
approximateArgumentConeType.functionTypeKind(session)?.isSuspendOrKSuspendFunction != true
|
||||||
|
) {
|
||||||
|
approximatedConeKotlinFunctionType = approximatedConeKotlinFunctionType.customFunctionTypeToSimpleFunctionType(session)
|
||||||
|
}
|
||||||
|
|
||||||
if (approximateArgumentConeType.isSubtypeOf(approximatedConeKotlinFunctionType, session)) {
|
if (approximateArgumentConeType.isSubtypeOf(approximatedConeKotlinFunctionType, session)) {
|
||||||
return argument
|
return argument
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
MODULE main
|
|
||||||
CLASS Kt50477EnabledKt$box$1.class
|
|
||||||
Property: class.signature
|
|
||||||
K1
|
|
||||||
NULL
|
|
||||||
K2
|
|
||||||
Lkotlin/jvm/internal/FunctionReferenceImpl;Lkotlin/jvm/functions/Function1<Lkotlin/coroutines/Continuation<-Lkotlin/Unit;>;Ljava/lang/Object;>;Lkotlin/coroutines/jvm/internal/SuspendFunction;
|
|
||||||
Property: class.superClassInternalName
|
|
||||||
K1
|
|
||||||
java/lang/Object
|
|
||||||
K2
|
|
||||||
kotlin/jvm/internal/FunctionReferenceImpl
|
|
||||||
Property: class.superInterfaces
|
|
||||||
K1
|
|
||||||
[FI, kotlin/jvm/internal/FunctionAdapter]
|
|
||||||
K2
|
|
||||||
[kotlin/coroutines/jvm/internal/SuspendFunction, kotlin/jvm/functions/Function1]
|
|
||||||
K1
|
|
||||||
call(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; [public, final]
|
|
||||||
K2
|
|
||||||
---
|
|
||||||
K1
|
|
||||||
equals(Ljava/lang/Object;)Z [public, final]
|
|
||||||
K2
|
|
||||||
---
|
|
||||||
K1
|
|
||||||
getFunctionDelegate()Lkotlin/Function; [public, final]
|
|
||||||
K2
|
|
||||||
---
|
|
||||||
K1
|
|
||||||
hashCode()I [public, final]
|
|
||||||
K2
|
|
||||||
---
|
|
||||||
K1
|
|
||||||
---
|
|
||||||
K2
|
|
||||||
invoke(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; [public, final]
|
|
||||||
CLASS Kt50477EnabledKt$box$4.class
|
|
||||||
Property: class.signature
|
|
||||||
K1
|
|
||||||
NULL
|
|
||||||
K2
|
|
||||||
Lkotlin/jvm/internal/FunctionReferenceImpl;Lkotlin/jvm/functions/Function1<Lkotlin/coroutines/Continuation<-Lkotlin/Unit;>;Ljava/lang/Object;>;Lkotlin/coroutines/jvm/internal/SuspendFunction;
|
|
||||||
Property: class.superClassInternalName
|
|
||||||
K1
|
|
||||||
java/lang/Object
|
|
||||||
K2
|
|
||||||
kotlin/jvm/internal/FunctionReferenceImpl
|
|
||||||
Property: class.superInterfaces
|
|
||||||
K1
|
|
||||||
[FI, kotlin/jvm/internal/FunctionAdapter]
|
|
||||||
K2
|
|
||||||
[kotlin/coroutines/jvm/internal/SuspendFunction, kotlin/jvm/functions/Function1]
|
|
||||||
K1
|
|
||||||
call(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; [public, final]
|
|
||||||
K2
|
|
||||||
---
|
|
||||||
K1
|
|
||||||
equals(Ljava/lang/Object;)Z [public, final]
|
|
||||||
K2
|
|
||||||
---
|
|
||||||
K1
|
|
||||||
getFunctionDelegate()Lkotlin/Function; [public, final]
|
|
||||||
K2
|
|
||||||
---
|
|
||||||
K1
|
|
||||||
hashCode()I [public, final]
|
|
||||||
K2
|
|
||||||
---
|
|
||||||
K1
|
|
||||||
---
|
|
||||||
K2
|
|
||||||
invoke(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; [public, final]
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
// !LANGUAGE: +SuspendOnlySamConversions
|
// !LANGUAGE: +SuspendOnlySamConversions
|
||||||
// TARGET_BACKEND: JVM_IR
|
// TARGET_BACKEND: JVM_IR
|
||||||
// JVM_ABI_K1_K2_DIFF: KT-62855
|
|
||||||
|
|
||||||
fun interface FI {
|
fun interface FI {
|
||||||
suspend fun call() // suspending now(!!!)
|
suspend fun call() // suspending now(!!!)
|
||||||
|
|||||||
-31
@@ -1,31 +0,0 @@
|
|||||||
MODULE main
|
|
||||||
Missing in K1
|
|
||||||
ChainedFunSuspendConversionForSimpleExpressionKt$sam$SuspendRunnable$0.class
|
|
||||||
CLASS ChainedFunSuspendConversionForSimpleExpressionKt$test$2.class
|
|
||||||
Property: class.signature
|
|
||||||
K1
|
|
||||||
NULL
|
|
||||||
K2
|
|
||||||
Lkotlin/jvm/internal/FunctionReferenceImpl;Lkotlin/jvm/functions/Function1<Lkotlin/coroutines/Continuation<-Lkotlin/Unit;>;Ljava/lang/Object;>;Lkotlin/coroutines/jvm/internal/SuspendFunction;
|
|
||||||
Property: class.superClassInternalName
|
|
||||||
K1
|
|
||||||
java/lang/Object
|
|
||||||
K2
|
|
||||||
kotlin/jvm/internal/FunctionReferenceImpl
|
|
||||||
Property: class.superInterfaces
|
|
||||||
K1
|
|
||||||
[SuspendRunnable, kotlin/jvm/internal/FunctionAdapter]
|
|
||||||
K2
|
|
||||||
[kotlin/coroutines/jvm/internal/SuspendFunction, kotlin/jvm/functions/Function1]
|
|
||||||
K1
|
|
||||||
equals(Ljava/lang/Object;)Z [public, final]
|
|
||||||
K2
|
|
||||||
---
|
|
||||||
K1
|
|
||||||
getFunctionDelegate()Lkotlin/Function; [public, final]
|
|
||||||
K2
|
|
||||||
---
|
|
||||||
K1
|
|
||||||
hashCode()I [public, final]
|
|
||||||
K2
|
|
||||||
---
|
|
||||||
Vendored
-1
@@ -1,6 +1,5 @@
|
|||||||
// !LANGUAGE: +SuspendConversion
|
// !LANGUAGE: +SuspendConversion
|
||||||
// IGNORE_BACKEND: JVM
|
// IGNORE_BACKEND: JVM
|
||||||
// JVM_ABI_K1_K2_DIFF: KT-62855
|
|
||||||
|
|
||||||
fun interface SuspendRunnable {
|
fun interface SuspendRunnable {
|
||||||
suspend fun invoke()
|
suspend fun invoke()
|
||||||
|
|||||||
Vendored
-1
@@ -2,6 +2,5 @@ MODULE main
|
|||||||
Missing in K1
|
Missing in K1
|
||||||
Test1$Scope$bar$1.class
|
Test1$Scope$bar$1.class
|
||||||
Test2$Scope$bar$1.class
|
Test2$Scope$bar$1.class
|
||||||
SuspendAndFunConversionInDisabledModeKt$sam$SuspendRunnable$0.class
|
|
||||||
Missing in K2
|
Missing in K2
|
||||||
SuspendAndFunConversionInDisabledModeKt$sam$Runnable$0.class
|
SuspendAndFunConversionInDisabledModeKt$sam$Runnable$0.class
|
||||||
|
|||||||
Vendored
+27
-30
@@ -31,37 +31,34 @@ FILE fqName:<root> fileName:/chainedFunSuspendConversionForSimpleExpression.kt
|
|||||||
VALUE_PARAMETER name:f index:0 type:kotlin.Function0<kotlin.Unit>
|
VALUE_PARAMETER name:f index:0 type:kotlin.Function0<kotlin.Unit>
|
||||||
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: BLOCK type=<root>.SuspendRunnable origin=SUSPEND_CONVERSION
|
||||||
TYPE_OP type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=IMPLICIT_CAST typeOperand=kotlin.coroutines.SuspendFunction0<kotlin.Unit>
|
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> ($receiver:kotlin.Function0<kotlin.Unit>) returnType:kotlin.Unit [suspend]
|
||||||
BLOCK type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=SUSPEND_CONVERSION
|
$receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:callee type:kotlin.Function0<kotlin.Unit>
|
||||||
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> ($receiver:kotlin.Function0<kotlin.Unit>) returnType:kotlin.Unit [suspend]
|
BLOCK_BODY
|
||||||
$receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:callee type:kotlin.Function0<kotlin.Unit>
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 declared in kotlin.Function0' type=kotlin.Unit origin=null
|
||||||
BLOCK_BODY
|
$this: GET_VAR 'callee: kotlin.Function0<kotlin.Unit> declared in <root>.test.suspendConversion' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
CALL 'public abstract fun invoke (): R of kotlin.Function0 declared in kotlin.Function0' type=kotlin.Unit origin=null
|
TYPE_OP type=<root>.SuspendRunnable origin=SAM_CONVERSION typeOperand=<root>.SuspendRunnable
|
||||||
$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 declared in <root>.test' type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=SUSPEND_CONVERSION reflectionTarget=null
|
||||||
FUNCTION_REFERENCE 'local final fun suspendConversion (): kotlin.Unit 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
|
||||||
$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: BLOCK type=<root>.SuspendRunnable origin=SUSPEND_CONVERSION
|
||||||
TYPE_OP type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=IMPLICIT_CAST typeOperand=kotlin.coroutines.SuspendFunction0<kotlin.Unit>
|
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> ($receiver:kotlin.Function0<kotlin.Unit>) returnType:kotlin.Unit [suspend]
|
||||||
BLOCK type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=SUSPEND_CONVERSION
|
$receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:callee type:kotlin.Function0<kotlin.Unit>
|
||||||
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> ($receiver:kotlin.Function0<kotlin.Unit>) returnType:kotlin.Unit [suspend]
|
BLOCK_BODY
|
||||||
$receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:callee type:kotlin.Function0<kotlin.Unit>
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 declared in kotlin.Function0' type=kotlin.Unit origin=null
|
||||||
BLOCK_BODY
|
$this: GET_VAR 'callee: kotlin.Function0<kotlin.Unit> declared in <root>.test.suspendConversion' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
CALL 'public abstract fun invoke (): R of kotlin.Function0 declared in kotlin.Function0' type=kotlin.Unit origin=null
|
TYPE_OP type=<root>.SuspendRunnable origin=SAM_CONVERSION typeOperand=<root>.SuspendRunnable
|
||||||
$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 declared in <root>.test' type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=SUSPEND_CONVERSION reflectionTarget=null
|
||||||
FUNCTION_REFERENCE 'local final fun suspendConversion (): kotlin.Unit 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
|
||||||
$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: BLOCK type=<root>.SuspendRunnable origin=SUSPEND_CONVERSION
|
||||||
TYPE_OP type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=IMPLICIT_CAST typeOperand=kotlin.coroutines.SuspendFunction0<kotlin.Unit>
|
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> ($receiver:kotlin.Function0<kotlin.Unit>) returnType:kotlin.Unit [suspend]
|
||||||
BLOCK type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=SUSPEND_CONVERSION
|
$receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:callee type:kotlin.Function0<kotlin.Unit>
|
||||||
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> ($receiver:kotlin.Function0<kotlin.Unit>) returnType:kotlin.Unit [suspend]
|
BLOCK_BODY
|
||||||
$receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:callee type:kotlin.Function0<kotlin.Unit>
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 declared in kotlin.Function0' type=kotlin.Unit origin=null
|
||||||
BLOCK_BODY
|
$this: GET_VAR 'callee: kotlin.Function0<kotlin.Unit> declared in <root>.test.suspendConversion' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
CALL 'public abstract fun invoke (): R of kotlin.Function0 declared in kotlin.Function0' type=kotlin.Unit origin=null
|
TYPE_OP type=<root>.SuspendRunnable origin=SAM_CONVERSION typeOperand=<root>.SuspendRunnable
|
||||||
$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 declared in <root>.test' type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=SUSPEND_CONVERSION reflectionTarget=null
|
||||||
FUNCTION_REFERENCE 'local final fun suspendConversion (): kotlin.Unit declared in <root>.test' type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=SUSPEND_CONVERSION reflectionTarget=null
|
$receiver: GET_VAR 'var t: kotlin.Function0<kotlin.Unit> declared in <root>.test' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||||
$receiver: GET_VAR 'var t: kotlin.Function0<kotlin.Unit> declared in <root>.test' type=kotlin.Function0<kotlin.Unit> origin=null
|
|
||||||
|
|||||||
Reference in New Issue
Block a user