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 1ed478b8998..613483bb793 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 @@ -415,11 +415,26 @@ internal class AdapterGenerator( val samFirType = unwrappedArgument.resolvedType.let { it.removeExternalProjections() ?: it } val samType = samFirType.toIrType(ConversionTypeOrigin.DEFAULT) + // Make sure the converted IrType owner indeed has a single abstract method, since FunctionReferenceLowering relies on it. - return IrTypeOperatorCallImpl( - this.startOffset, this.endOffset, samType, IrTypeOperator.SAM_CONVERSION, samType, - castArgumentToFunctionalInterfaceForSamType(this, unwrappedArgument.expression.resolvedType, samFirType) - ) + fun IrExpression.generateSamConversion(samType: IrType, firSamConversion: FirSamConversionExpression, samFirType: ConeKotlinType) = + IrTypeOperatorCallImpl( + this.startOffset, this.endOffset, samType, IrTypeOperator.SAM_CONVERSION, samType, + castArgumentToFunctionalInterfaceForSamType(this, firSamConversion.expression.resolvedType, samFirType) + ) + + return if (this is IrBlock && origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE) { + // 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. + val lastIndex = statements.lastIndex + val samConversion = (statements[lastIndex] as IrExpression).generateSamConversion(samType, unwrappedArgument, samFirType) + statements[lastIndex] = samConversion + this.type = samConversion.type + this + } else { + generateSamConversion(samType, unwrappedArgument, samFirType) + } } // See org.jetbrains.kotlin.psi2ir.generators.ArgumentsGenerationUtilsKt.castArgumentToFunctionalInterfaceForSamType (K1 counterpart) diff --git a/compiler/testData/codegen/box/sam/kt49226.kt b/compiler/testData/codegen/box/sam/kt49226.kt index b7b4308281f..efc73f3bd0c 100644 --- a/compiler/testData/codegen/box/sam/kt49226.kt +++ b/compiler/testData/codegen/box/sam/kt49226.kt @@ -1,4 +1,6 @@ -// TARGET_BACKEND: JVM +// TARGET_BACKEND: JVM_IR +// CHECK_BYTECODE_LISTING +// ^Verify that no anonymous class is generated KT-63329 KT-62858, old backend gets this wrong. // FILE: kt49226.kt fun box(): String { diff --git a/compiler/testData/codegen/box/sam/kt49226.txt b/compiler/testData/codegen/box/sam/kt49226.txt new file mode 100644 index 00000000000..dc18bdacef4 --- /dev/null +++ b/compiler/testData/codegen/box/sam/kt49226.txt @@ -0,0 +1,7 @@ +@kotlin.Metadata +public final class Kt49226Kt { + // source: 'kt49226.kt' + private synthetic final static method box$arrayOf(p0: java.lang.String): java.lang.String[] + private final static method box$arrayOf__proxy(p0: java.lang.String): java.lang.String[] + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String +} diff --git a/compiler/testData/ir/irText/expressions/callableReferences/withAdaptationForSam.fir.ir.txt b/compiler/testData/ir/irText/expressions/callableReferences/withAdaptationForSam.fir.ir.txt index 58d6bc29986..c4363a6f4e6 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/withAdaptationForSam.fir.ir.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/withAdaptationForSam.fir.ir.txt @@ -28,12 +28,12 @@ FILE fqName: fileName:/withAdaptationForSam.kt FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY CALL 'public final fun useFoo (foo: .IFoo): kotlin.Unit declared in ' type=kotlin.Unit origin=null - foo: TYPE_OP type=.IFoo origin=SAM_CONVERSION typeOperand=.IFoo - BLOCK type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE - FUN ADAPTER_FOR_CALLABLE_REFERENCE name:withVararg visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Unit - VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:kotlin.Int - BLOCK_BODY - CALL 'public final fun withVararg (vararg xs: kotlin.Int): kotlin.Int declared in ' type=kotlin.Int origin=null - xs: VARARG type=kotlin.IntArray varargElementType=kotlin.Int - GET_VAR 'p0: kotlin.Int declared in .test.withVararg' type=kotlin.Int origin=null + foo: BLOCK type=.IFoo origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:withVararg visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Unit + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:kotlin.Int + BLOCK_BODY + CALL 'public final fun withVararg (vararg xs: kotlin.Int): kotlin.Int declared in ' type=kotlin.Int origin=null + xs: VARARG type=kotlin.IntArray varargElementType=kotlin.Int + GET_VAR 'p0: kotlin.Int declared in .test.withVararg' type=kotlin.Int origin=null + TYPE_OP type=.IFoo origin=SAM_CONVERSION typeOperand=.IFoo FUNCTION_REFERENCE 'local final fun withVararg (p0: kotlin.Int): kotlin.Unit declared in .test' type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE reflectionTarget=public final fun withVararg (vararg xs: kotlin.Int): kotlin.Int declared in diff --git a/compiler/testData/ir/irText/expressions/callableReferences/withAdaptationForSam.fir.kt.txt b/compiler/testData/ir/irText/expressions/callableReferences/withAdaptationForSam.fir.kt.txt index 7205e1690cf..5b8387c229f 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/withAdaptationForSam.fir.kt.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/withAdaptationForSam.fir.kt.txt @@ -16,7 +16,7 @@ fun test() { withVararg(xs = [p0]) } - ::withVararg - } /*-> IFoo */) + ::withVararg /*-> IFoo */ + }) } diff --git a/compiler/testData/ir/irText/expressions/funInterface/samConversionInVarargs.fir.ir.txt b/compiler/testData/ir/irText/expressions/funInterface/samConversionInVarargs.fir.ir.txt index 66dc4547842..4744d24c44b 100644 --- a/compiler/testData/ir/irText/expressions/funInterface/samConversionInVarargs.fir.ir.txt +++ b/compiler/testData/ir/irText/expressions/funInterface/samConversionInVarargs.fir.ir.txt @@ -65,12 +65,12 @@ FILE fqName: fileName:/samConversionInVarargs.kt BLOCK_BODY CALL 'public final fun useVararg (vararg foos: .IFoo): kotlin.Unit declared in ' type=kotlin.Unit origin=null foos: VARARG type=kotlin.Array.IFoo> varargElementType=.IFoo - TYPE_OP type=.IFoo origin=SAM_CONVERSION typeOperand=.IFoo - BLOCK type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE - FUN ADAPTER_FOR_CALLABLE_REFERENCE name:withVarargOfInt visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Unit - VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:kotlin.Int - BLOCK_BODY - CALL 'public final fun withVarargOfInt (vararg xs: kotlin.Int): kotlin.String declared in ' type=kotlin.String origin=null - xs: VARARG type=kotlin.IntArray varargElementType=kotlin.Int - GET_VAR 'p0: kotlin.Int declared in .testAdaptedCR.withVarargOfInt' type=kotlin.Int origin=null + BLOCK type=.IFoo origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:withVarargOfInt visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Unit + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:kotlin.Int + BLOCK_BODY + CALL 'public final fun withVarargOfInt (vararg xs: kotlin.Int): kotlin.String declared in ' type=kotlin.String origin=null + xs: VARARG type=kotlin.IntArray varargElementType=kotlin.Int + GET_VAR 'p0: kotlin.Int declared in .testAdaptedCR.withVarargOfInt' type=kotlin.Int origin=null + TYPE_OP type=.IFoo origin=SAM_CONVERSION typeOperand=.IFoo FUNCTION_REFERENCE 'local final fun withVarargOfInt (p0: kotlin.Int): kotlin.Unit declared in .testAdaptedCR' type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE reflectionTarget=public final fun withVarargOfInt (vararg xs: kotlin.Int): kotlin.String declared in diff --git a/compiler/testData/ir/irText/expressions/funInterface/samConversionInVarargs.fir.kt.txt b/compiler/testData/ir/irText/expressions/funInterface/samConversionInVarargs.fir.kt.txt index 100ac6975a5..ab0b4ee240a 100644 --- a/compiler/testData/ir/irText/expressions/funInterface/samConversionInVarargs.fir.kt.txt +++ b/compiler/testData/ir/irText/expressions/funInterface/samConversionInVarargs.fir.kt.txt @@ -36,7 +36,7 @@ fun testAdaptedCR() { withVarargOfInt(xs = [p0]) } - ::withVarargOfInt - } /*-> IFoo */]) + ::withVarargOfInt /*-> IFoo */ + }]) } diff --git a/compiler/testData/ir/irText/expressions/funInterface/samConversionOnCallableReference.fir.ir.txt b/compiler/testData/ir/irText/expressions/funInterface/samConversionOnCallableReference.fir.ir.txt index 160ffc42011..dc4b9912216 100644 --- a/compiler/testData/ir/irText/expressions/funInterface/samConversionOnCallableReference.fir.ir.txt +++ b/compiler/testData/ir/irText/expressions/funInterface/samConversionOnCallableReference.fir.ir.txt @@ -48,9 +48,9 @@ FILE fqName: fileName:/samConversionOnCallableReference.kt FUN name:testSamConversionOnAdapted visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY CALL 'public final fun use (r: .KRunnable): kotlin.Unit declared in ' type=kotlin.Unit origin=null - r: TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable - BLOCK type=kotlin.Function0 origin=ADAPTED_FUNCTION_REFERENCE - FUN ADAPTER_FOR_CALLABLE_REFERENCE name:foo1 visibility:local modality:FINAL <> () returnType:kotlin.Unit - BLOCK_BODY - CALL 'public final fun foo1 (vararg xs: kotlin.Int): kotlin.Int declared in ' type=kotlin.Int origin=null + r: BLOCK type=.KRunnable origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:foo1 visibility:local modality:FINAL <> () returnType:kotlin.Unit + BLOCK_BODY + CALL 'public final fun foo1 (vararg xs: kotlin.Int): kotlin.Int declared in ' type=kotlin.Int origin=null + TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable FUNCTION_REFERENCE 'local final fun foo1 (): kotlin.Unit declared in .testSamConversionOnAdapted' type=kotlin.Function0 origin=ADAPTED_FUNCTION_REFERENCE reflectionTarget=public final fun foo1 (vararg xs: kotlin.Int): kotlin.Int declared in diff --git a/compiler/testData/ir/irText/expressions/funInterface/samConversionOnCallableReference.fir.kt.txt b/compiler/testData/ir/irText/expressions/funInterface/samConversionOnCallableReference.fir.kt.txt index 34748adea95..ce6ace75d9e 100644 --- a/compiler/testData/ir/irText/expressions/funInterface/samConversionOnCallableReference.fir.kt.txt +++ b/compiler/testData/ir/irText/expressions/funInterface/samConversionOnCallableReference.fir.kt.txt @@ -37,7 +37,7 @@ fun testSamConversionOnAdapted() { foo1() } - ::foo1 - } /*-> KRunnable */) + ::foo1 /*-> KRunnable */ + }) } diff --git a/compiler/testData/ir/irText/expressions/suspendConversionWithFunInterfaces.fir.ir.txt b/compiler/testData/ir/irText/expressions/suspendConversionWithFunInterfaces.fir.ir.txt index 19abe67cdba..e9c9c166b21 100644 --- a/compiler/testData/ir/irText/expressions/suspendConversionWithFunInterfaces.fir.ir.txt +++ b/compiler/testData/ir/irText/expressions/suspendConversionWithFunInterfaces.fir.ir.txt @@ -40,23 +40,23 @@ FILE fqName: fileName:/suspendConversionWithFunInterfaces.kt FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY CALL 'public final fun foo1 (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=ADAPTED_FUNCTION_REFERENCE - FUN ADAPTER_FOR_CALLABLE_REFERENCE name:bar1 visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend] - BLOCK_BODY - CALL 'public final fun bar1 (): kotlin.Unit declared in ' type=kotlin.Unit origin=null + s: BLOCK type=.SuspendRunnable origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:bar1 visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend] + BLOCK_BODY + CALL 'public final fun bar1 (): kotlin.Unit declared in ' type=kotlin.Unit origin=null + TYPE_OP type=.SuspendRunnable origin=SAM_CONVERSION typeOperand=.SuspendRunnable FUNCTION_REFERENCE 'local final fun bar1 (): kotlin.Unit declared in .box' type=kotlin.coroutines.SuspendFunction0 origin=ADAPTED_FUNCTION_REFERENCE reflectionTarget=public final fun bar1 (): kotlin.Unit declared in CALL 'public final fun foo1 (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=ADAPTED_FUNCTION_REFERENCE - FUN ADAPTER_FOR_CALLABLE_REFERENCE name:bar2 visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend] - BLOCK_BODY - CALL 'public final fun bar2 (s: kotlin.String): kotlin.Int declared in ' type=kotlin.Int origin=null + s: BLOCK type=.SuspendRunnable origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:bar2 visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend] + BLOCK_BODY + CALL 'public final fun bar2 (s: kotlin.String): kotlin.Int declared in ' type=kotlin.Int origin=null + TYPE_OP type=.SuspendRunnable origin=SAM_CONVERSION typeOperand=.SuspendRunnable FUNCTION_REFERENCE 'local final fun bar2 (): kotlin.Unit declared in .box' type=kotlin.coroutines.SuspendFunction0 origin=ADAPTED_FUNCTION_REFERENCE reflectionTarget=public final fun bar2 (s: kotlin.String): kotlin.Int declared in CALL 'public final fun foo1 (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=ADAPTED_FUNCTION_REFERENCE - FUN ADAPTER_FOR_CALLABLE_REFERENCE name:bar3 visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend] - BLOCK_BODY - CALL 'public final fun bar3 (): kotlin.Unit declared in ' type=kotlin.Unit origin=null + s: BLOCK type=.SuspendRunnable origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:bar3 visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend] + BLOCK_BODY + CALL 'public final fun bar3 (): kotlin.Unit declared in ' type=kotlin.Unit origin=null + TYPE_OP type=.SuspendRunnable origin=SAM_CONVERSION typeOperand=.SuspendRunnable FUNCTION_REFERENCE 'local final fun bar3 (): kotlin.Unit declared in .box' type=kotlin.coroutines.SuspendFunction0 origin=ADAPTED_FUNCTION_REFERENCE reflectionTarget=public final fun bar3 (): kotlin.Unit declared in diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 401ba114083..159fb76388b 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -47105,12 +47105,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/sam/kt4753_2.kt"); } - @Test - @TestMetadata("kt49226.kt") - public void testKt49226() throws Exception { - runTest("compiler/testData/codegen/box/sam/kt49226.kt"); - } - @Test @TestMetadata("kt50108.kt") public void testKt50108() throws Exception {