diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt index 68e4ea3c098..b30c1a32359 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt @@ -5,6 +5,7 @@ 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.Modality import org.jetbrains.kotlin.fir.backend.* @@ -423,7 +424,7 @@ internal class AdapterGenerator( 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 // 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. @@ -445,13 +446,21 @@ internal class AdapterGenerator( ): IrExpression { // 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. - 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 // 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. 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)) { return argument } diff --git a/compiler/testData/codegen/box/sam/kt50477Enabled.jvm_abi.txt b/compiler/testData/codegen/box/sam/kt50477Enabled.jvm_abi.txt deleted file mode 100644 index 7c8105a9123..00000000000 --- a/compiler/testData/codegen/box/sam/kt50477Enabled.jvm_abi.txt +++ /dev/null @@ -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;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;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] diff --git a/compiler/testData/codegen/box/sam/kt50477Enabled.kt b/compiler/testData/codegen/box/sam/kt50477Enabled.kt index ac6f69d0152..f16df138c0a 100644 --- a/compiler/testData/codegen/box/sam/kt50477Enabled.kt +++ b/compiler/testData/codegen/box/sam/kt50477Enabled.kt @@ -1,6 +1,5 @@ // !LANGUAGE: +SuspendOnlySamConversions // TARGET_BACKEND: JVM_IR -// JVM_ABI_K1_K2_DIFF: KT-62855 fun interface FI { suspend fun call() // suspending now(!!!) diff --git a/compiler/testData/codegen/box/suspendConversion/chainedFunSuspendConversionForSimpleExpression.jvm_abi.txt b/compiler/testData/codegen/box/suspendConversion/chainedFunSuspendConversionForSimpleExpression.jvm_abi.txt deleted file mode 100644 index eed46d241d9..00000000000 --- a/compiler/testData/codegen/box/suspendConversion/chainedFunSuspendConversionForSimpleExpression.jvm_abi.txt +++ /dev/null @@ -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;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 - --- diff --git a/compiler/testData/codegen/box/suspendConversion/chainedFunSuspendConversionForSimpleExpression.kt b/compiler/testData/codegen/box/suspendConversion/chainedFunSuspendConversionForSimpleExpression.kt index d69383d3709..e44ea4e6b3f 100644 --- a/compiler/testData/codegen/box/suspendConversion/chainedFunSuspendConversionForSimpleExpression.kt +++ b/compiler/testData/codegen/box/suspendConversion/chainedFunSuspendConversionForSimpleExpression.kt @@ -1,6 +1,5 @@ // !LANGUAGE: +SuspendConversion // IGNORE_BACKEND: JVM -// JVM_ABI_K1_K2_DIFF: KT-62855 fun interface SuspendRunnable { suspend fun invoke() diff --git a/compiler/testData/codegen/box/suspendConversion/suspendAndFunConversionInDisabledMode.jvm_abi.txt b/compiler/testData/codegen/box/suspendConversion/suspendAndFunConversionInDisabledMode.jvm_abi.txt index fd1850dd96e..11d379dfca4 100644 --- a/compiler/testData/codegen/box/suspendConversion/suspendAndFunConversionInDisabledMode.jvm_abi.txt +++ b/compiler/testData/codegen/box/suspendConversion/suspendAndFunConversionInDisabledMode.jvm_abi.txt @@ -2,6 +2,5 @@ MODULE main Missing in K1 Test1$Scope$bar$1.class Test2$Scope$bar$1.class - SuspendAndFunConversionInDisabledModeKt$sam$SuspendRunnable$0.class Missing in K2 SuspendAndFunConversionInDisabledModeKt$sam$Runnable$0.class diff --git a/compiler/testData/ir/irText/expressions/chainedFunSuspendConversionForSimpleExpression.fir.ir.txt b/compiler/testData/ir/irText/expressions/chainedFunSuspendConversionForSimpleExpression.fir.ir.txt index 26e704c67d9..d7050bcab4d 100644 --- a/compiler/testData/ir/irText/expressions/chainedFunSuspendConversionForSimpleExpression.fir.ir.txt +++ b/compiler/testData/ir/irText/expressions/chainedFunSuspendConversionForSimpleExpression.fir.ir.txt @@ -31,37 +31,34 @@ FILE fqName: fileName:/chainedFunSuspendConversionForSimpleExpression.kt VALUE_PARAMETER name:f index:0 type:kotlin.Function0 BLOCK_BODY CALL 'public final fun foo (s: .SuspendRunnable): kotlin.Unit declared in ' type=kotlin.Unit origin=null - s: TYPE_OP type=.SuspendRunnable origin=SAM_CONVERSION typeOperand=.SuspendRunnable - TYPE_OP type=kotlin.coroutines.SuspendFunction0 origin=IMPLICIT_CAST typeOperand=kotlin.coroutines.SuspendFunction0 - BLOCK type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION - FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> ($receiver:kotlin.Function0) returnType:kotlin.Unit [suspend] - $receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:callee type:kotlin.Function0 - BLOCK_BODY - CALL 'public abstract fun invoke (): R of kotlin.Function0 declared in kotlin.Function0' type=kotlin.Unit origin=null - $this: GET_VAR 'callee: kotlin.Function0 declared in .test.suspendConversion' type=kotlin.Function0 origin=null - FUNCTION_REFERENCE 'local final fun suspendConversion (): kotlin.Unit declared in .test' type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION reflectionTarget=null - $receiver: GET_VAR 'f: kotlin.Function0 declared in .test' type=kotlin.Function0 origin=null + s: BLOCK type=.SuspendRunnable origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> ($receiver:kotlin.Function0) returnType:kotlin.Unit [suspend] + $receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:callee type:kotlin.Function0 + BLOCK_BODY + CALL 'public abstract fun invoke (): R of kotlin.Function0 declared in kotlin.Function0' type=kotlin.Unit origin=null + $this: GET_VAR 'callee: kotlin.Function0 declared in .test.suspendConversion' type=kotlin.Function0 origin=null + TYPE_OP type=.SuspendRunnable origin=SAM_CONVERSION typeOperand=.SuspendRunnable + FUNCTION_REFERENCE 'local final fun suspendConversion (): kotlin.Unit declared in .test' type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION reflectionTarget=null + $receiver: GET_VAR 'f: kotlin.Function0 declared in .test' type=kotlin.Function0 origin=null CALL 'public final fun foo (s: .SuspendRunnable): kotlin.Unit declared in ' type=kotlin.Unit origin=null - s: TYPE_OP type=.SuspendRunnable origin=SAM_CONVERSION typeOperand=.SuspendRunnable - TYPE_OP type=kotlin.coroutines.SuspendFunction0 origin=IMPLICIT_CAST typeOperand=kotlin.coroutines.SuspendFunction0 - BLOCK type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION - FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> ($receiver:kotlin.Function0) returnType:kotlin.Unit [suspend] - $receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:callee type:kotlin.Function0 - BLOCK_BODY - CALL 'public abstract fun invoke (): R of kotlin.Function0 declared in kotlin.Function0' type=kotlin.Unit origin=null - $this: GET_VAR 'callee: kotlin.Function0 declared in .test.suspendConversion' type=kotlin.Function0 origin=null - FUNCTION_REFERENCE 'local final fun suspendConversion (): kotlin.Unit declared in .test' type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION reflectionTarget=null - $receiver: CALL 'public final fun bar (): kotlin.Function0 declared in ' type=kotlin.Function0 origin=null + s: BLOCK type=.SuspendRunnable origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> ($receiver:kotlin.Function0) returnType:kotlin.Unit [suspend] + $receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:callee type:kotlin.Function0 + BLOCK_BODY + CALL 'public abstract fun invoke (): R of kotlin.Function0 declared in kotlin.Function0' type=kotlin.Unit origin=null + $this: GET_VAR 'callee: kotlin.Function0 declared in .test.suspendConversion' type=kotlin.Function0 origin=null + TYPE_OP type=.SuspendRunnable origin=SAM_CONVERSION typeOperand=.SuspendRunnable + FUNCTION_REFERENCE 'local final fun suspendConversion (): kotlin.Unit declared in .test' type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION reflectionTarget=null + $receiver: CALL 'public final fun bar (): kotlin.Function0 declared in ' type=kotlin.Function0 origin=null VAR name:t type:kotlin.Function0 [var] GET_VAR 'f: kotlin.Function0 declared in .test' type=kotlin.Function0 origin=null CALL 'public final fun foo (s: .SuspendRunnable): kotlin.Unit declared in ' type=kotlin.Unit origin=null - s: TYPE_OP type=.SuspendRunnable origin=SAM_CONVERSION typeOperand=.SuspendRunnable - TYPE_OP type=kotlin.coroutines.SuspendFunction0 origin=IMPLICIT_CAST typeOperand=kotlin.coroutines.SuspendFunction0 - BLOCK type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION - FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> ($receiver:kotlin.Function0) returnType:kotlin.Unit [suspend] - $receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:callee type:kotlin.Function0 - BLOCK_BODY - CALL 'public abstract fun invoke (): R of kotlin.Function0 declared in kotlin.Function0' type=kotlin.Unit origin=null - $this: GET_VAR 'callee: kotlin.Function0 declared in .test.suspendConversion' type=kotlin.Function0 origin=null - FUNCTION_REFERENCE 'local final fun suspendConversion (): kotlin.Unit declared in .test' type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION reflectionTarget=null - $receiver: GET_VAR 'var t: kotlin.Function0 declared in .test' type=kotlin.Function0 origin=null + s: BLOCK type=.SuspendRunnable origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> ($receiver:kotlin.Function0) returnType:kotlin.Unit [suspend] + $receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:callee type:kotlin.Function0 + BLOCK_BODY + CALL 'public abstract fun invoke (): R of kotlin.Function0 declared in kotlin.Function0' type=kotlin.Unit origin=null + $this: GET_VAR 'callee: kotlin.Function0 declared in .test.suspendConversion' type=kotlin.Function0 origin=null + TYPE_OP type=.SuspendRunnable origin=SAM_CONVERSION typeOperand=.SuspendRunnable + FUNCTION_REFERENCE 'local final fun suspendConversion (): kotlin.Unit declared in .test' type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION reflectionTarget=null + $receiver: GET_VAR 'var t: kotlin.Function0 declared in .test' type=kotlin.Function0 origin=null