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 bc88167f326..b3ca25031a4 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 @@ -44,6 +44,7 @@ import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi2ir.generators.implicitCastTo import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.model.TypeVariance @@ -443,7 +444,25 @@ internal class AdapterGenerator( val samType = samFirType.toIrType(ConversionTypeContext.DEFAULT) // Make sure the converted IrType owner indeed has a single abstract method, since FunctionReferenceLowering relies on it. if (!samType.isSamType) return this - return IrTypeOperatorCallImpl(this.startOffset, this.endOffset, samType, IrTypeOperator.SAM_CONVERSION, samType, this) + return IrTypeOperatorCallImpl( + this.startOffset, this.endOffset, samType, IrTypeOperator.SAM_CONVERSION, samType, + castArgumentToFunctionalInterfaceForSamType(this, argument.typeRef.coneType, samFirType) + ) + } + + // See org.jetbrains.kotlin.psi2ir.generators.ArgumentsGenerationUtilsKt.castArgumentToFunctionalInterfaceForSamType (K1 counterpart) + private fun castArgumentToFunctionalInterfaceForSamType( + argument: IrExpression, + argumentConeType: ConeKotlinType, + samType: ConeKotlinType + ): IrExpression { + val coneKotlinFunctionType = getFunctionTypeForPossibleSamType(samType) ?: 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. + if (argumentConeType.isSubtypeOf(coneKotlinFunctionType, session)) return argument + val irFunctionType = coneKotlinFunctionType.toIrType() + return argument.implicitCastTo(irFunctionType) } // This function is mostly a mirror of org.jetbrains.kotlin.backend.common.SamTypeApproximator.removeExternalProjections diff --git a/compiler/testData/ir/irText/expressions/chainedFunSuspendConversionForSimpleExpression.fir.ir.txt b/compiler/testData/ir/irText/expressions/chainedFunSuspendConversionForSimpleExpression.fir.ir.txt index da398e97deb..6772ebf733e 100644 --- a/compiler/testData/ir/irText/expressions/chainedFunSuspendConversionForSimpleExpression.fir.ir.txt +++ b/compiler/testData/ir/irText/expressions/chainedFunSuspendConversionForSimpleExpression.fir.ir.txt @@ -32,33 +32,36 @@ FILE fqName: fileName:/chainedFunSuspendConversionForSimpleExpression.kt 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 - 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 [operator] 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 [suspend] 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 + 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 [operator] 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 [suspend] 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 - 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 [operator] 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 [suspend] 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 + 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 [operator] 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 [suspend] 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 - 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 [operator] 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 [suspend] declared in .test' type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION reflectionTarget=null - $receiver: GET_VAR 'var t: kotlin.Function0 [var] declared in .test' type=kotlin.Function0 origin=null + 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 [operator] 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 [suspend] declared in .test' type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION reflectionTarget=null + $receiver: GET_VAR 'var t: kotlin.Function0 [var] declared in .test' type=kotlin.Function0 origin=null diff --git a/compiler/testData/ir/irText/firProblems/kt19251.fir.ir.txt b/compiler/testData/ir/irText/firProblems/kt19251.fir.ir.txt index 707632c37af..952033b40fd 100644 --- a/compiler/testData/ir/irText/firProblems/kt19251.fir.ir.txt +++ b/compiler/testData/ir/irText/firProblems/kt19251.fir.ir.txt @@ -18,9 +18,10 @@ FILE fqName: fileName:/test.kt $this: GET_VAR 'val map: kotlin.collections.MutableMap<.Fun, kotlin.String> [val] declared in .box' type=kotlin.collections.MutableMap<.Fun, kotlin.String> origin=null p0: GET_VAR 'val fn: .Fun [val] declared in .box' type=.Fun origin=null p1: TYPE_OP type=@[EnhancedNullability] java.util.function.Function origin=SAM_CONVERSION typeOperand=@[EnhancedNullability] java.util.function.Function - FUN_EXPR type=kotlin.Function1<@[EnhancedNullability] .Fun, @[EnhancedNullability] kotlin.String> origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:@[EnhancedNullability] .Fun) returnType:@[EnhancedNullability] kotlin.String - VALUE_PARAMETER name:it index:0 type:@[EnhancedNullability] .Fun - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (it: @[EnhancedNullability] .Fun): @[EnhancedNullability] kotlin.String declared in .box' - CONST String type=kotlin.String value="OK" + TYPE_OP type=kotlin.Function1<@[EnhancedNullability] kotlin.Any?, @[EnhancedNullability] kotlin.String> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<@[EnhancedNullability] kotlin.Any?, @[EnhancedNullability] kotlin.String> + FUN_EXPR type=kotlin.Function1<@[EnhancedNullability] .Fun, @[EnhancedNullability] kotlin.String> origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:@[EnhancedNullability] .Fun) returnType:@[EnhancedNullability] kotlin.String + VALUE_PARAMETER name:it index:0 type:@[EnhancedNullability] .Fun + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (it: @[EnhancedNullability] .Fun): @[EnhancedNullability] kotlin.String declared in .box' + CONST String type=kotlin.String value="OK" diff --git a/compiler/testData/ir/irText/firProblems/kt19251.fir.kt.txt b/compiler/testData/ir/irText/firProblems/kt19251.fir.kt.txt index 5425b0b218b..cf710bd0530 100644 --- a/compiler/testData/ir/irText/firProblems/kt19251.fir.kt.txt +++ b/compiler/testData/ir/irText/firProblems/kt19251.fir.kt.txt @@ -7,5 +7,5 @@ fun box(): String { return map.computeIfAbsent(p0 = fn, p1 = local fun (it: @EnhancedNullability Fun): @EnhancedNullability String { return "OK" } - /*-> @EnhancedNullability Function */) /*!! String */ + /*as Function1<@EnhancedNullability Any?, @EnhancedNullability String> */ /*-> @EnhancedNullability Function */) /*!! String */ }