diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index 4278e135f22..97592f4ad68 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -30,22 +30,20 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl +import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor import org.jetbrains.kotlin.ir.descriptors.WrappedValueParameterDescriptor import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.types.IrSimpleType -import org.jetbrains.kotlin.ir.types.IrType -import org.jetbrains.kotlin.ir.types.classifierOrNull -import org.jetbrains.kotlin.ir.types.toArrayOrPrimitiveArrayType -import org.jetbrains.kotlin.ir.types.typeOrNull +import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtPropertyDelegate import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects +import org.jetbrains.kotlin.utils.SmartList class CallAndReferenceGenerator( private val components: Fir2IrComponents, @@ -98,9 +96,11 @@ class CallAndReferenceGenerator( is IrFunctionSymbol -> { val function = symbol.owner // TODO: should refer to LanguageVersionSettings.SuspendConversion - if (requiresSuspendConversion(type, function)) { + if (requiresCoercionToUnit(type, function) || + requiresSuspendConversion(type, function) + ) { val adaptedType = callableReferenceAccess.typeRef.coneType.kFunctionTypeToFunctionType() - generateAdaptedCallableReference(callableReferenceAccess, symbol, adaptedType) + generateAdaptedCallableReference(callableReferenceAccess, explicitReceiverExpression, symbol, adaptedType) } else { IrFunctionReferenceImpl( startOffset, endOffset, type, symbol, @@ -119,6 +119,14 @@ class CallAndReferenceGenerator( }.applyTypeArguments(callableReferenceAccess).applyReceivers(callableReferenceAccess, explicitReceiverExpression) } + private fun requiresCoercionToUnit(type: IrType, function: IrFunction): Boolean { + if (!type.isFunctionTypeOrSubtype()) { + return false + } + val expectedReturnType = (type as? IrSimpleType)?.arguments?.last()?.typeOrNull + return expectedReturnType?.isUnit() == true && !function.returnType.isUnit() + } + private fun requiresSuspendConversion(type: IrType, function: IrFunction): Boolean = type.isKSuspendFunction() && !function.isSuspend @@ -133,33 +141,73 @@ class CallAndReferenceGenerator( private fun generateAdaptedCallableReference( callableReferenceAccess: FirCallableReferenceAccess, + explicitReceiverExpression: IrExpression?, adapteeSymbol: IrFunctionSymbol, type: IrSimpleType ): IrExpression { val firAdaptee = callableReferenceAccess.toResolvedCallableReference()?.resolvedSymbol?.fir as? FirSimpleFunction val adaptee = adapteeSymbol.owner - // TODO: handle bound receiver, e.g., c::foo + val expectedReturnType = type.arguments.last().typeOrNull return callableReferenceAccess.convertWithOffsets { startOffset, endOffset -> - val irAdapterFunction = createAdapterFunctionForSuspendConversion(startOffset, endOffset, firAdaptee!!, adaptee, type) - val irCall = createAdapteeCall(callableReferenceAccess, adapteeSymbol, irAdapterFunction) + val boundDispatchReceiver = callableReferenceAccess.findBoundReceiver(explicitReceiverExpression, isDispatch = true) + val boundExtensionReceiver = callableReferenceAccess.findBoundReceiver(explicitReceiverExpression, isDispatch = false) + + val irAdapterFunction = createAdapterFunction( + callableReferenceAccess, startOffset, endOffset, firAdaptee!!, adaptee, type, boundDispatchReceiver, boundExtensionReceiver + ) + val irCall = createAdapteeCall( + callableReferenceAccess, adapteeSymbol, irAdapterFunction, boundDispatchReceiver, boundExtensionReceiver + ) irAdapterFunction.body = irFactory.createBlockBody(startOffset, endOffset) { - if (firAdaptee.returnTypeRef.isUnit) { + if (expectedReturnType?.isUnit() == true) { statements.add(irCall) } else { statements.add(IrReturnImpl(startOffset, endOffset, irBuiltIns.nothingType, irAdapterFunction.symbol, irCall)) } } - IrFunctionExpressionImpl(startOffset, endOffset, type, irAdapterFunction, IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE) + // TODO: handle transient receiver, such as class symbol, like A::foo + val boundReceiver = boundDispatchReceiver ?: boundExtensionReceiver + if (boundReceiver == null) { + IrFunctionExpressionImpl(startOffset, endOffset, type, irAdapterFunction, IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE) + } else { + val irAdapterRef = IrFunctionReferenceImpl( + startOffset, endOffset, type, irAdapterFunction.symbol, irAdapterFunction.typeParameters.size, + irAdapterFunction.valueParameters.size, null, IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE + ) + val statements = SmartList() + if (boundReceiver.isSafeToUseWithoutCopying()) { + irAdapterRef.extensionReceiver = boundReceiver + } else { + val (irVariable, irVariableSymbol) = + createTemporaryVariableForSafeCallConstruction(boundReceiver.deepCopyWithSymbols(), conversionScope) + irAdapterRef.extensionReceiver = IrGetValueImpl(startOffset, endOffset, irVariableSymbol) + statements.add(irVariable) + } + statements.add(irAdapterFunction) + statements.add(irAdapterRef) + + IrBlockImpl(startOffset, endOffset, type, IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE, statements) + } } } - private fun createAdapterFunctionForSuspendConversion( + // TODO: refactor/reuse the same logic in ReflectionReferencesGenerator + private fun IrExpression.isSafeToUseWithoutCopying() = + this is IrGetObjectValue || + this is IrGetEnumValue || + this is IrConst<*> || + this is IrGetValue && symbol.isBound && symbol.owner.isImmutable + + private fun createAdapterFunction( + callableReferenceAccess: FirCallableReferenceAccess, startOffset: Int, endOffset: Int, firAdaptee: FirSimpleFunction, adaptee: IrFunction, type: IrSimpleType, + boundDispatchReceiver: IrExpression?, + boundExtensionReceiver: IrExpression? ): IrSimpleFunction { val returnType = type.arguments.last().typeOrNull!! val parameterTypes = type.arguments.dropLast(1).map { it.typeOrNull!! } @@ -176,7 +224,7 @@ class CallAndReferenceGenerator( isInline = firAdaptee.isInline, isExternal = firAdaptee.isExternal, isTailrec = firAdaptee.isTailRec, - isSuspend = true, + isSuspend = firAdaptee.isSuspend || type.isSuspendFunction(), isOperator = firAdaptee.isOperator, isInfix = firAdaptee.isInfix, isExpect = firAdaptee.isExpect, @@ -184,11 +232,24 @@ class CallAndReferenceGenerator( ).also { irAdapterFunction -> adapterFunctionDescriptor.bind(irAdapterFunction) irAdapterFunction.metadata = FirMetadataSource.Function(firAdaptee) + symbolTable.enterScope(irAdapterFunction) + irAdapterFunction.dispatchReceiverParameter = null + val boundReceiver = boundDispatchReceiver ?: boundExtensionReceiver + when { + boundReceiver == null -> + irAdapterFunction.extensionReceiverParameter = null + boundDispatchReceiver != null && boundExtensionReceiver != null -> + error("Bound callable references can't have both receivers: ${callableReferenceAccess.render()}") + else -> + irAdapterFunction.extensionReceiverParameter = + createAdapterParameter(irAdapterFunction, Name.identifier("receiver"), -1, boundReceiver.type) + } irAdapterFunction.valueParameters += parameterTypes.mapIndexed { index, parameterType -> createAdapterParameter(irAdapterFunction, Name.identifier("p$index"), index, parameterType) } symbolTable.leaveScope(irAdapterFunction) + irAdapterFunction.parent = conversionScope.parent()!! } } @@ -226,7 +287,9 @@ class CallAndReferenceGenerator( private fun createAdapteeCall( callableReferenceAccess: FirCallableReferenceAccess, adapteeSymbol: IrFunctionSymbol, - adapterFunction: IrFunction + adapterFunction: IrFunction, + boundDispatchReceiver: IrExpression?, + boundExtensionReceiver: IrExpression? ): IrExpression { val adapteeFunction = adapteeSymbol.owner val startOffset = adapteeFunction.startOffset @@ -248,7 +311,15 @@ class CallAndReferenceGenerator( ) } - // TODO: handle non-transient, bound dispatch/extension receiver + if (boundDispatchReceiver != null || boundExtensionReceiver != null) { + val receiverValue = IrGetValueImpl( + startOffset, endOffset, adapterFunction.extensionReceiverParameter!!.symbol, IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE + ) + when { + boundDispatchReceiver != null -> irCall.dispatchReceiver = receiverValue + boundExtensionReceiver != null -> irCall.extensionReceiver = receiverValue + } + } adapteeFunction.valueParameters.mapIndexed { index, valueParameter -> when { @@ -680,6 +751,14 @@ class CallAndReferenceGenerator( } } + private fun FirQualifiedAccess.findBoundReceiver(explicitReceiverExpression: IrExpression?, isDispatch: Boolean): IrExpression? { + val firReceiver = if (isDispatch) dispatchReceiver else extensionReceiver + if (firReceiver == null || firReceiver is FirNoReceiverExpression) { + return null + } + return findIrReceiver(explicitReceiverExpression, isDispatch) + } + private fun IrExpression.applyReceivers(qualifiedAccess: FirQualifiedAccess, explicitReceiverExpression: IrExpression?): IrExpression { return when (this) { is IrMemberAccessExpression<*> -> { diff --git a/compiler/testData/codegen/box/callableReference/equality/coercionToUnitWithDefaults.kt b/compiler/testData/codegen/box/callableReference/equality/coercionToUnitWithDefaults.kt index be983cc7618..e4849f22dfc 100644 --- a/compiler/testData/codegen/box/callableReference/equality/coercionToUnitWithDefaults.kt +++ b/compiler/testData/codegen/box/callableReference/equality/coercionToUnitWithDefaults.kt @@ -1,6 +1,5 @@ // IGNORE_BACKEND: JS, JS_IR, NATIVE // IGNORE_BACKEND: JS_IR_ES6 -// IGNORE_BACKEND_FIR: JVM_IR // FILE: test.kt fun checkEqual(x: Any, y: Any) { diff --git a/compiler/testData/codegen/box/callableReference/equality/coercionToUnitWithVararg.kt b/compiler/testData/codegen/box/callableReference/equality/coercionToUnitWithVararg.kt index c1effbabd69..9f291914263 100644 --- a/compiler/testData/codegen/box/callableReference/equality/coercionToUnitWithVararg.kt +++ b/compiler/testData/codegen/box/callableReference/equality/coercionToUnitWithVararg.kt @@ -1,6 +1,5 @@ // IGNORE_BACKEND: JS, JS_IR, NATIVE // IGNORE_BACKEND: JS_IR_ES6 -// IGNORE_BACKEND_FIR: JVM_IR // FILE: test.kt fun checkEqual(x: Any, y: Any) { diff --git a/compiler/testData/codegen/box/callableReference/serializability/adaptedReferences.kt b/compiler/testData/codegen/box/callableReference/serializability/adaptedReferences.kt index 89736604ce4..ead65b36610 100644 --- a/compiler/testData/codegen/box/callableReference/serializability/adaptedReferences.kt +++ b/compiler/testData/codegen/box/callableReference/serializability/adaptedReferences.kt @@ -1,3 +1,4 @@ +// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM // WITH_REFLECT diff --git a/compiler/testData/ir/irText/expressions/callableReferences/adaptedWithCoercionToUnit.fir.txt b/compiler/testData/ir/irText/expressions/callableReferences/adaptedWithCoercionToUnit.fir.txt index 764aeb4d34d..c272dd0f371 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/adaptedWithCoercionToUnit.fir.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/adaptedWithCoercionToUnit.fir.txt @@ -23,19 +23,34 @@ FILE fqName: fileName:/adaptedWithCoercionToUnit.kt BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun test0 (): kotlin.Unit declared in ' CALL 'public final fun useUnit0 (fn: kotlin.Function0): kotlin.Unit declared in ' type=kotlin.Unit origin=null - fn: FUNCTION_REFERENCE 'public final fun fn0 (): kotlin.Int declared in ' type=kotlin.reflect.KFunction0 origin=null reflectionTarget= + fn: FUN_EXPR type=kotlin.Function0 origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:fn0 visibility:local modality:FINAL <> () returnType:kotlin.Unit + BLOCK_BODY + CALL 'public final fun fn0 (): kotlin.Int declared in ' type=kotlin.Int origin=null FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun test1 (): kotlin.Unit declared in ' CALL 'public final fun useUnit1 (fn: kotlin.Function1): kotlin.Unit declared in ' type=kotlin.Unit origin=null - fn: FUNCTION_REFERENCE 'public final fun fn1 (x: kotlin.Int): kotlin.Int declared in ' type=kotlin.reflect.KFunction1 origin=null reflectionTarget= + fn: FUN_EXPR type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:fn1 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 fn1 (x: kotlin.Int): kotlin.Int declared in ' type=kotlin.Int origin=null + x: GET_VAR 'p0: kotlin.Int declared in .test1.fn1' type=kotlin.Int origin=null FUN name:testV0 visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun testV0 (): kotlin.Unit declared in ' CALL 'public final fun useUnit0 (fn: kotlin.Function0): kotlin.Unit declared in ' type=kotlin.Unit origin=null - fn: FUNCTION_REFERENCE 'public final fun fnv (vararg xs: kotlin.Int): kotlin.Int declared in ' type=kotlin.reflect.KFunction0 origin=null reflectionTarget= + fn: FUN_EXPR type=kotlin.Function0 origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:fnv visibility:local modality:FINAL <> () returnType:kotlin.Unit + BLOCK_BODY + CALL 'public final fun fnv (vararg xs: kotlin.Int): kotlin.Int declared in ' type=kotlin.Int origin=null FUN name:testV1 visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun testV1 (): kotlin.Unit declared in ' CALL 'public final fun useUnit1 (fn: kotlin.Function1): kotlin.Unit declared in ' type=kotlin.Unit origin=null - fn: FUNCTION_REFERENCE 'public final fun fnv (vararg xs: kotlin.Int): kotlin.Int declared in ' type=kotlin.reflect.KFunction1 origin=null reflectionTarget= + fn: FUN_EXPR type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:fnv 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 fnv (vararg xs: kotlin.Int): kotlin.Int declared in ' type=kotlin.Int origin=null diff --git a/compiler/testData/ir/irText/expressions/callableReferences/boundInlineAdaptedReference.fir.txt b/compiler/testData/ir/irText/expressions/callableReferences/boundInlineAdaptedReference.fir.txt index a5fef3bec64..1fc2b6fc985 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/boundInlineAdaptedReference.fir.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/boundInlineAdaptedReference.fir.txt @@ -14,5 +14,11 @@ FILE fqName:test fileName:/boundInlineAdaptedReference.kt FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY CALL 'public final fun foo (x: kotlin.Function0): kotlin.Unit [inline] declared in test' type=kotlin.Unit origin=null - x: FUNCTION_REFERENCE 'public final fun id (s: kotlin.String, vararg xs: kotlin.Int): kotlin.String declared in test' type=kotlin.reflect.KFunction0 origin=null reflectionTarget= - $receiver: CONST String type=kotlin.String value="Fail" + x: BLOCK type=kotlin.Function0 origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:id visibility:local modality:FINAL <> ($receiver:kotlin.String) returnType:kotlin.Unit + $receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:receiver type:kotlin.String + BLOCK_BODY + CALL 'public final fun id (s: kotlin.String, vararg xs: kotlin.Int): kotlin.String declared in test' type=kotlin.String origin=null + $receiver: GET_VAR 'receiver: kotlin.String declared in test.test.id' type=kotlin.String origin=ADAPTED_FUNCTION_REFERENCE + FUNCTION_REFERENCE 'local final fun id (): kotlin.Unit declared in test.test' type=kotlin.Function0 origin=ADAPTED_FUNCTION_REFERENCE reflectionTarget=null + $receiver: CONST String type=kotlin.String value="Fail" diff --git a/compiler/testData/ir/irText/expressions/callableReferences/suspendConversion.fir.txt b/compiler/testData/ir/irText/expressions/callableReferences/suspendConversion.fir.txt index 6f83550b68c..8ed79f2dc26 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/suspendConversion.fir.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/suspendConversion.fir.txt @@ -94,8 +94,7 @@ FILE fqName: fileName:/suspendConversion.kt fn: FUN_EXPR type=kotlin.coroutines.SuspendFunction0 origin=ADAPTED_FUNCTION_REFERENCE FUN ADAPTER_FOR_CALLABLE_REFERENCE name:foo3 visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend] BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun foo3 (): kotlin.Unit [suspend] declared in .testWithCoercionToUnit' - CALL 'public final fun foo3 (): kotlin.Int declared in ' type=kotlin.Int origin=null + CALL 'public final fun foo3 (): kotlin.Int declared in ' type=kotlin.Int origin=null FUN name:testWithDefaults visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY CALL 'public final fun useSuspend (fn: kotlin.coroutines.SuspendFunction0): kotlin.Unit declared in ' type=kotlin.Unit origin=null @@ -106,7 +105,13 @@ FILE fqName: fileName:/suspendConversion.kt FUN name:testWithBoundReceiver visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY CALL 'public final fun useSuspend (fn: kotlin.coroutines.SuspendFunction0): kotlin.Unit declared in ' type=kotlin.Unit origin=null - fn: FUN_EXPR type=kotlin.coroutines.SuspendFunction0 origin=ADAPTED_FUNCTION_REFERENCE - FUN ADAPTER_FOR_CALLABLE_REFERENCE name:bar visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend] + fn: BLOCK type=kotlin.coroutines.SuspendFunction0 origin=ADAPTED_FUNCTION_REFERENCE + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:.C [val] + CONSTRUCTOR_CALL 'public constructor () [primary] declared in .C' type=.C origin=null + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:bar visibility:local modality:FINAL <> ($receiver:.C) returnType:kotlin.Unit [suspend] + $receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:receiver type:.C BLOCK_BODY CALL 'public final fun bar (): kotlin.Unit declared in .C' type=kotlin.Unit origin=null + $this: GET_VAR 'receiver: .C declared in .testWithBoundReceiver.bar' type=.C origin=ADAPTED_FUNCTION_REFERENCE + FUNCTION_REFERENCE 'local final fun bar (): kotlin.Unit [suspend] declared in .testWithBoundReceiver' type=kotlin.coroutines.SuspendFunction0 origin=ADAPTED_FUNCTION_REFERENCE reflectionTarget=null + $receiver: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .C' type=.C origin=null diff --git a/compiler/testData/ir/irText/expressions/callableReferences/unboundMemberReferenceWithAdaptedArguments.fir.txt b/compiler/testData/ir/irText/expressions/callableReferences/unboundMemberReferenceWithAdaptedArguments.fir.txt index 9c822812070..d771cf96f96 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/unboundMemberReferenceWithAdaptedArguments.fir.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/unboundMemberReferenceWithAdaptedArguments.fir.txt @@ -60,15 +60,34 @@ FILE fqName: fileName:/unboundMemberReferenceWithAdaptedArguments.kt FUN name:testUnbound visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY CALL 'public final fun use1 (fn: kotlin.Function2<.A, kotlin.Int, kotlin.Unit>): kotlin.Unit declared in ' type=kotlin.Unit origin=null - fn: FUNCTION_REFERENCE 'public open fun foo (vararg xs: kotlin.Int): kotlin.Int declared in .A' type=kotlin.reflect.KFunction2<.A, kotlin.Int, kotlin.Unit> origin=null reflectionTarget= + fn: FUN_EXPR type=kotlin.Function2<.A, kotlin.Int, kotlin.Unit> origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:foo visibility:local modality:FINAL <> (p0:.A, p1:kotlin.Int) returnType:kotlin.Unit + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:.A + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p1 index:1 type:kotlin.Int + BLOCK_BODY + CALL 'public open fun foo (vararg xs: kotlin.Int): kotlin.Int declared in .A' type=kotlin.Int origin=null FUN name:testBound visibility:public modality:FINAL <> (a:.A) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:.A BLOCK_BODY CALL 'public final fun use2 (fn: kotlin.Function1): kotlin.Unit declared in ' type=kotlin.Unit origin=null - fn: FUNCTION_REFERENCE 'public open fun foo (vararg xs: kotlin.Int): kotlin.Int declared in .A' type=kotlin.reflect.KFunction1 origin=null reflectionTarget= - $this: GET_VAR 'a: .A declared in .testBound' type=.A origin=null + fn: BLOCK type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:foo visibility:local modality:FINAL <> ($receiver:.A, p0:kotlin.Int) returnType:kotlin.Unit + $receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:receiver type:.A + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:kotlin.Int + BLOCK_BODY + CALL 'public open fun foo (vararg xs: kotlin.Int): kotlin.Int declared in .A' type=kotlin.Int origin=null + $this: GET_VAR 'receiver: .A declared in .testBound.foo' type=.A origin=ADAPTED_FUNCTION_REFERENCE + FUNCTION_REFERENCE 'local final fun foo (p0: kotlin.Int): kotlin.Unit declared in .testBound' type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE reflectionTarget=null + $receiver: GET_VAR 'a: .A declared in .testBound' type=.A origin=null FUN name:testObject visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY CALL 'public final fun use2 (fn: kotlin.Function1): kotlin.Unit declared in ' type=kotlin.Unit origin=null - fn: FUNCTION_REFERENCE 'public final fun foo (vararg xs: kotlin.Int): kotlin.Int declared in .Obj' type=kotlin.reflect.KFunction1 origin=null reflectionTarget= - $this: GET_OBJECT 'CLASS OBJECT name:Obj modality:FINAL visibility:public superTypes:[.A]' type=.Obj + fn: BLOCK type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:foo visibility:local modality:FINAL <> ($receiver:.Obj, p0:kotlin.Int) returnType:kotlin.Unit + $receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:receiver type:.Obj + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:kotlin.Int + BLOCK_BODY + CALL 'public final fun foo (vararg xs: kotlin.Int): kotlin.Int declared in .Obj' type=kotlin.Int origin=null + $this: GET_VAR 'receiver: .Obj declared in .testObject.foo' type=.Obj origin=ADAPTED_FUNCTION_REFERENCE + FUNCTION_REFERENCE 'local final fun foo (p0: kotlin.Int): kotlin.Unit declared in .testObject' type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE reflectionTarget=null + $receiver: GET_OBJECT 'CLASS OBJECT name:Obj modality:FINAL visibility:public superTypes:[.A]' type=.Obj diff --git a/compiler/testData/ir/irText/expressions/callableReferences/withAdaptationForSam.fir.txt b/compiler/testData/ir/irText/expressions/callableReferences/withAdaptationForSam.fir.txt index 66ffdfe69de..724d82ed2b8 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/withAdaptationForSam.fir.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/withAdaptationForSam.fir.txt @@ -29,4 +29,8 @@ FILE fqName: fileName:/withAdaptationForSam.kt 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 - FUNCTION_REFERENCE 'public final fun withVararg (vararg xs: kotlin.Int): kotlin.Int declared in ' type=kotlin.reflect.KFunction1 origin=null reflectionTarget= + FUN_EXPR 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 diff --git a/compiler/testData/ir/irText/expressions/callableReferences/withAdaptedArguments.fir.txt b/compiler/testData/ir/irText/expressions/callableReferences/withAdaptedArguments.fir.txt index 1b9d9b745c0..ad536991955 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/withAdaptedArguments.fir.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/withAdaptedArguments.fir.txt @@ -77,7 +77,12 @@ FILE fqName: fileName:/withAdaptedArguments.kt BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun testCoercionToUnit (): kotlin.Unit declared in ' CALL 'public final fun coerceToUnit (fn: kotlin.Function1): kotlin.Unit declared in ' type=kotlin.Unit origin=null - fn: FUNCTION_REFERENCE 'public final fun fnWithDefault (a: kotlin.Int, b: kotlin.Int): kotlin.String declared in ' type=kotlin.reflect.KFunction1 origin=null reflectionTarget= + fn: FUN_EXPR type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:fnWithDefault 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 fnWithDefault (a: kotlin.Int, b: kotlin.Int): kotlin.String declared in ' type=kotlin.String origin=null + a: GET_VAR 'p0: kotlin.Int declared in .testCoercionToUnit.fnWithDefault' type=kotlin.Int origin=null FUN name:testImportedObjectMember visibility:public modality:FINAL <> () returnType:kotlin.String BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun testImportedObjectMember (): kotlin.String declared in ' diff --git a/compiler/testData/ir/irText/expressions/callableReferences/withArgumentAdaptationAndReceiver.fir.txt b/compiler/testData/ir/irText/expressions/callableReferences/withArgumentAdaptationAndReceiver.fir.txt index f56077c7b6f..23666ea474e 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/withArgumentAdaptationAndReceiver.fir.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/withArgumentAdaptationAndReceiver.fir.txt @@ -21,37 +21,75 @@ FILE fqName: fileName:/withArgumentAdaptationAndReceiver.kt $this: VALUE_PARAMETER name: type:.Host BLOCK_BODY CALL 'public final fun use (fn: kotlin.Function1): kotlin.Unit declared in ' type=kotlin.Unit origin=null - fn: FUNCTION_REFERENCE 'public final fun withVararg (vararg xs: kotlin.Int): kotlin.String declared in .Host' type=kotlin.reflect.KFunction1 origin=null reflectionTarget= - $this: GET_VAR ': .Host declared in .Host.testImplicitThis' type=.Host origin=null + fn: BLOCK type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:withVararg visibility:local modality:FINAL <> ($receiver:.Host, p0:kotlin.Int) returnType:kotlin.Unit + $receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:receiver type:.Host + 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.String declared in .Host' type=kotlin.String origin=null + $this: GET_VAR 'receiver: .Host declared in .Host.testImplicitThis.withVararg' type=.Host origin=ADAPTED_FUNCTION_REFERENCE + FUNCTION_REFERENCE 'local final fun withVararg (p0: kotlin.Int): kotlin.Unit declared in .Host.testImplicitThis' type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE reflectionTarget=null FUN name:testBoundReceiverLocalVal visibility:public modality:FINAL <> ($this:.Host) returnType:kotlin.Unit $this: VALUE_PARAMETER name: type:.Host BLOCK_BODY VAR name:h type:.Host [val] CONSTRUCTOR_CALL 'public constructor () [primary] declared in .Host' type=.Host origin=null CALL 'public final fun use (fn: kotlin.Function1): kotlin.Unit declared in ' type=kotlin.Unit origin=null - fn: FUNCTION_REFERENCE 'public final fun withVararg (vararg xs: kotlin.Int): kotlin.String declared in .Host' type=kotlin.reflect.KFunction1 origin=null reflectionTarget= - $this: GET_VAR 'val h: .Host [val] declared in .Host.testBoundReceiverLocalVal' type=.Host origin=null + fn: BLOCK type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:withVararg visibility:local modality:FINAL <> ($receiver:.Host, p0:kotlin.Int) returnType:kotlin.Unit + $receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:receiver type:.Host + 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.String declared in .Host' type=kotlin.String origin=null + $this: GET_VAR 'receiver: .Host declared in .Host.testBoundReceiverLocalVal.withVararg' type=.Host origin=ADAPTED_FUNCTION_REFERENCE + FUNCTION_REFERENCE 'local final fun withVararg (p0: kotlin.Int): kotlin.Unit declared in .Host.testBoundReceiverLocalVal' type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE reflectionTarget=null + $receiver: GET_VAR 'val h: .Host [val] declared in .Host.testBoundReceiverLocalVal' type=.Host origin=null FUN name:testBoundReceiverLocalVar visibility:public modality:FINAL <> ($this:.Host) returnType:kotlin.Unit $this: VALUE_PARAMETER name: type:.Host BLOCK_BODY VAR name:h type:.Host [var] CONSTRUCTOR_CALL 'public constructor () [primary] declared in .Host' type=.Host origin=null CALL 'public final fun use (fn: kotlin.Function1): kotlin.Unit declared in ' type=kotlin.Unit origin=null - fn: FUNCTION_REFERENCE 'public final fun withVararg (vararg xs: kotlin.Int): kotlin.String declared in .Host' type=kotlin.reflect.KFunction1 origin=null reflectionTarget= - $this: GET_VAR 'var h: .Host [var] declared in .Host.testBoundReceiverLocalVar' type=.Host origin=null + fn: BLOCK type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:.Host [val] + GET_VAR 'var h: .Host [var] declared in .Host.testBoundReceiverLocalVar' type=.Host origin=null + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:withVararg visibility:local modality:FINAL <> ($receiver:.Host, p0:kotlin.Int) returnType:kotlin.Unit + $receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:receiver type:.Host + 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.String declared in .Host' type=kotlin.String origin=null + $this: GET_VAR 'receiver: .Host declared in .Host.testBoundReceiverLocalVar.withVararg' type=.Host origin=ADAPTED_FUNCTION_REFERENCE + FUNCTION_REFERENCE 'local final fun withVararg (p0: kotlin.Int): kotlin.Unit declared in .Host.testBoundReceiverLocalVar' type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE reflectionTarget=null + $receiver: GET_VAR 'var h: .Host [var] declared in .Host.testBoundReceiverLocalVar' type=.Host origin=null FUN name:testBoundReceiverParameter visibility:public modality:FINAL <> ($this:.Host, h:.Host) returnType:kotlin.Unit $this: VALUE_PARAMETER name: type:.Host VALUE_PARAMETER name:h index:0 type:.Host BLOCK_BODY CALL 'public final fun use (fn: kotlin.Function1): kotlin.Unit declared in ' type=kotlin.Unit origin=null - fn: FUNCTION_REFERENCE 'public final fun withVararg (vararg xs: kotlin.Int): kotlin.String declared in .Host' type=kotlin.reflect.KFunction1 origin=null reflectionTarget= - $this: GET_VAR 'h: .Host declared in .Host.testBoundReceiverParameter' type=.Host origin=null + fn: BLOCK type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:withVararg visibility:local modality:FINAL <> ($receiver:.Host, p0:kotlin.Int) returnType:kotlin.Unit + $receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:receiver type:.Host + 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.String declared in .Host' type=kotlin.String origin=null + $this: GET_VAR 'receiver: .Host declared in .Host.testBoundReceiverParameter.withVararg' type=.Host origin=ADAPTED_FUNCTION_REFERENCE + FUNCTION_REFERENCE 'local final fun withVararg (p0: kotlin.Int): kotlin.Unit declared in .Host.testBoundReceiverParameter' type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE reflectionTarget=null + $receiver: GET_VAR 'h: .Host declared in .Host.testBoundReceiverParameter' type=.Host origin=null FUN name:testBoundReceiverExpression visibility:public modality:FINAL <> ($this:.Host) returnType:kotlin.Unit $this: VALUE_PARAMETER name: type:.Host BLOCK_BODY CALL 'public final fun use (fn: kotlin.Function1): kotlin.Unit declared in ' type=kotlin.Unit origin=null - fn: FUNCTION_REFERENCE 'public final fun withVararg (vararg xs: kotlin.Int): kotlin.String declared in .Host' type=kotlin.reflect.KFunction1 origin=null reflectionTarget= - $this: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .Host' type=.Host origin=null + fn: BLOCK type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE + VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:.Host [val] + CONSTRUCTOR_CALL 'public constructor () [primary] declared in .Host' type=.Host origin=null + FUN ADAPTER_FOR_CALLABLE_REFERENCE name:withVararg visibility:local modality:FINAL <> ($receiver:.Host, p0:kotlin.Int) returnType:kotlin.Unit + $receiver: VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:receiver type:.Host + 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.String declared in .Host' type=kotlin.String origin=null + $this: GET_VAR 'receiver: .Host declared in .Host.testBoundReceiverExpression.withVararg' type=.Host origin=ADAPTED_FUNCTION_REFERENCE + FUNCTION_REFERENCE 'local final fun withVararg (p0: kotlin.Int): kotlin.Unit declared in .Host.testBoundReceiverExpression' type=kotlin.Function1 origin=ADAPTED_FUNCTION_REFERENCE reflectionTarget=null + $receiver: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .Host' type=.Host origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/testData/ir/irText/expressions/funInterface/samConversionInVarargs.fir.txt b/compiler/testData/ir/irText/expressions/funInterface/samConversionInVarargs.fir.txt index d397ac785b5..d9afb3cfadc 100644 --- a/compiler/testData/ir/irText/expressions/funInterface/samConversionInVarargs.fir.txt +++ b/compiler/testData/ir/irText/expressions/funInterface/samConversionInVarargs.fir.txt @@ -61,4 +61,8 @@ 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 - FUNCTION_REFERENCE 'public final fun withVarargOfInt (vararg xs: kotlin.Int): kotlin.String declared in ' type=kotlin.reflect.KFunction1 origin=null reflectionTarget= + FUN_EXPR 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 diff --git a/compiler/testData/ir/irText/expressions/funInterface/samConversionOnCallableReference.fir.txt b/compiler/testData/ir/irText/expressions/funInterface/samConversionOnCallableReference.fir.txt index fdf8029e62b..1a2d9efe7a6 100644 --- a/compiler/testData/ir/irText/expressions/funInterface/samConversionOnCallableReference.fir.txt +++ b/compiler/testData/ir/irText/expressions/funInterface/samConversionOnCallableReference.fir.txt @@ -35,7 +35,10 @@ FILE fqName: fileName:/samConversionOnCallableReference.kt BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun testSamCosntructorOnAdapted (): .KRunnable declared in ' TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable - FUNCTION_REFERENCE 'public final fun foo1 (vararg xs: kotlin.Int): kotlin.Int declared in ' type=kotlin.reflect.KFunction0 origin=null reflectionTarget= + FUN_EXPR 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 FUN name:testSamConversion 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 @@ -45,4 +48,7 @@ FILE fqName: fileName:/samConversionOnCallableReference.kt 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 - FUNCTION_REFERENCE 'public final fun foo1 (vararg xs: kotlin.Int): kotlin.Int declared in ' type=kotlin.reflect.KFunction0 origin=null reflectionTarget= + FUN_EXPR 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