From 27a144f86fc771901a0bab715e9e10423e4dcd75 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Mon, 29 Nov 2021 17:01:28 +0300 Subject: [PATCH] PSI2IR KT-47939 callable references to fun interface constructors --- .../runners/ir/Fir2IrTextTestGenerated.java | 6 + .../ReflectionReferencesGenerator.kt | 138 +++++++++++++++--- .../ir/declarations/IrDeclarationOrigin.kt | 3 + .../ir/expressions/IrStatementOrigin.kt | 3 +- .../funInterfaceConstructorReference.ir.txt | 128 ++++++++++++++++ .../funInterfaceConstructorReference.kt | 36 +++++ .../funInterfaceConstructorReference.kt.txt | 74 ++++++++++ .../test/runners/ir/IrTextTestGenerated.java | 6 + .../kotlin/ir/KlibTextTestCaseGenerated.java | 5 + 9 files changed, 376 insertions(+), 23 deletions(-) create mode 100644 compiler/testData/ir/irText/expressions/funInterfaceConstructorReference.ir.txt create mode 100644 compiler/testData/ir/irText/expressions/funInterfaceConstructorReference.kt create mode 100644 compiler/testData/ir/irText/expressions/funInterfaceConstructorReference.kt.txt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java index 07fa0ca96be..c75df2a8046 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java @@ -1394,6 +1394,12 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest { runTest("compiler/testData/ir/irText/expressions/funImportedFromObject.kt"); } + @Test + @TestMetadata("funInterfaceConstructorReference.kt") + public void testFunInterfaceConstructorReference() throws Exception { + runTest("compiler/testData/ir/irText/expressions/funInterfaceConstructorReference.kt"); + } + @Test @TestMetadata("genericConstructorCallWithTypeArguments.kt") public void testGenericConstructorCallWithTypeArguments() throws Exception { diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ReflectionReferencesGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ReflectionReferencesGenerator.kt index c0a987cdc4b..e9e6c186bf9 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ReflectionReferencesGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ReflectionReferencesGenerator.kt @@ -18,8 +18,12 @@ package org.jetbrains.kotlin.psi2ir.generators import org.jetbrains.kotlin.builtins.* import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.synthetic.FunctionInterfaceConstructorDescriptor import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET -import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.DescriptorMetadataSource +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.descriptors.IrBuiltInsOverDescriptors import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* @@ -67,32 +71,122 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St fun generateCallableReference(ktCallableReference: KtCallableReferenceExpression): IrExpression { val resolvedCall = getResolvedCall(ktCallableReference.callableReference)!! val resolvedDescriptor = resolvedCall.resultingDescriptor - + val callableReferenceType = getTypeInferredByFrontendOrFail(ktCallableReference) val callBuilder = unwrapCallableDescriptorAndTypeArguments(resolvedCall) - val callableReferenceType = getTypeInferredByFrontendOrFail(ktCallableReference) - if (resolvedCall.valueArguments.isNotEmpty() || + return when { + resolvedDescriptor is FunctionInterfaceConstructorDescriptor || + resolvedDescriptor.original is FunctionInterfaceConstructorDescriptor -> + generateFunctionInterfaceConstructorReference( + ktCallableReference, callableReferenceType, callBuilder.descriptor + ) + + isAdaptedCallableReference(resolvedCall, resolvedDescriptor, callableReferenceType) -> + generateAdaptedCallableReference(ktCallableReference, callBuilder, callableReferenceType) + + else -> + statementGenerator.generateCallReceiver( + ktCallableReference, + resolvedDescriptor, + resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver,resolvedCall.contextReceivers, + isSafe = false + ).call { dispatchReceiverValue, extensionReceiverValue, _ -> + generateCallableReference( + ktCallableReference, + callableReferenceType, + callBuilder.descriptor, + callBuilder.typeArguments + ).also { irCallableReference -> + irCallableReference.dispatchReceiver = dispatchReceiverValue?.loadIfExists() + irCallableReference.extensionReceiver = extensionReceiverValue?.loadIfExists() + } + } + } + } + + private fun isAdaptedCallableReference( + resolvedCall: ResolvedCall, + resolvedDescriptor: CallableDescriptor, + callableReferenceType: KotlinType + ) = resolvedCall.valueArguments.isNotEmpty() || requiresCoercionToUnit(resolvedDescriptor, callableReferenceType) || requiresSuspendConversion(resolvedDescriptor, callableReferenceType) - ) { - return generateAdaptedCallableReference(ktCallableReference, callBuilder, callableReferenceType) - } - return statementGenerator.generateCallReceiver( - ktCallableReference, - resolvedDescriptor, resolvedCall.dispatchReceiver, - resolvedCall.extensionReceiver, - resolvedCall.contextReceivers, - isSafe = false - ).call { dispatchReceiverValue, extensionReceiverValue, _ -> - generateCallableReference( - ktCallableReference, - callableReferenceType, - callBuilder.descriptor, - callBuilder.typeArguments - ).also { irCallableReference -> - irCallableReference.dispatchReceiver = dispatchReceiverValue?.loadIfExists() - irCallableReference.extensionReceiver = extensionReceiverValue?.loadIfExists() + private fun generateFunctionInterfaceConstructorReference( + ktCallableReference: KtCallableReferenceExpression, + callableReferenceType: KotlinType, + descriptor: CallableDescriptor + ): IrExpression { + // { + // fun (function: ): = + // (function) + // :: + // } + val startOffset = ktCallableReference.startOffsetSkippingComments + val endOffset = ktCallableReference.endOffset + + val irReferenceType = callableReferenceType.toIrType() + + val irAdapterFun = createFunInterfaceConstructorAdapter(startOffset, endOffset, descriptor) + + val irAdapterRef = IrFunctionReferenceImpl( + startOffset, endOffset, + type = irReferenceType, + symbol = irAdapterFun.symbol, + typeArgumentsCount = irAdapterFun.typeParameters.size, + valueArgumentsCount = irAdapterFun.valueParameters.size, + reflectionTarget = irAdapterFun.symbol, + origin = IrStatementOrigin.FUN_INTERFACE_CONSTRUCTOR_REFERENCE + ) + + return IrBlockImpl( + startOffset, endOffset, + irReferenceType, + IrStatementOrigin.FUN_INTERFACE_CONSTRUCTOR_REFERENCE, + listOf( + irAdapterFun, + irAdapterRef + ) + ) + } + + private fun createFunInterfaceConstructorAdapter(startOffset: Int, endOffset: Int, descriptor: CallableDescriptor): IrSimpleFunction { + val samType = descriptor.returnType + ?: throw AssertionError("Unresolved return type: $descriptor") + val samClassDescriptor = samType.constructor.declarationDescriptor as? ClassDescriptor + ?: throw AssertionError("Class type expected: $samType") + val irSamType = samType.toIrType() + + val functionParameter = descriptor.valueParameters.singleOrNull() + ?: throw AssertionError("Single value parameter expected: $descriptor") + + return context.irFactory.createFunction( + startOffset, endOffset, + IrDeclarationOrigin.ADAPTER_FOR_FUN_INTERFACE_CONSTRUCTOR, + IrSimpleFunctionSymbolImpl(), + name = samClassDescriptor.name, + visibility = DescriptorVisibilities.LOCAL, + modality = Modality.FINAL, + returnType = irSamType, + isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isOperator = false, isInfix = false, + isExpect = false, isFakeOverride = false + ).also { irAdapterFun -> + context.symbolTable.withScope(irAdapterFun) { + // TODO irAdapterFun.metadata = ...? + irAdapterFun.dispatchReceiverParameter = null + irAdapterFun.extensionReceiverParameter = null + + val irFnParameter = createAdapterParameter(startOffset, endOffset, functionParameter.name, 0, functionParameter.type) + irAdapterFun.valueParameters = listOf(irFnParameter) + irAdapterFun.body = + context.irFactory.createExpressionBody( + startOffset, endOffset, + IrTypeOperatorCallImpl( + startOffset, endOffset, + irSamType, IrTypeOperator.SAM_CONVERSION, irSamType, + IrGetValueImpl(startOffset, endOffset, irFnParameter.symbol) + ) + ) } } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationOrigin.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationOrigin.kt index c2691f4394b..b0695103923 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationOrigin.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationOrigin.kt @@ -16,6 +16,8 @@ package org.jetbrains.kotlin.ir.declarations +import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl + interface IrDeclarationOrigin { object DEFINED : IrDeclarationOriginImpl("DEFINED") object FAKE_OVERRIDE : IrDeclarationOriginImpl("FAKE_OVERRIDE") @@ -75,6 +77,7 @@ interface IrDeclarationOrigin { object ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE : IrDeclarationOriginImpl("ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE") object ADAPTER_FOR_SUSPEND_CONVERSION : IrDeclarationOriginImpl("ADAPTER_FOR_SUSPEND_CONVERSION", isSynthetic = true) object ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION : IrDeclarationOriginImpl("ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION") + object ADAPTER_FOR_FUN_INTERFACE_CONSTRUCTOR : IrDeclarationOriginImpl("ADAPTER_FOR_FUN_INTERFACE_CONSTRUCTOR", isSynthetic = true) object GENERATED_SAM_IMPLEMENTATION : IrDeclarationOriginImpl("GENERATED_SAM_IMPLEMENTATION") object SYNTHETIC_GENERATED_SAM_IMPLEMENTATION : IrDeclarationOriginImpl("SYNTHETIC_GENERATED_SAM_IMPLEMENTATION", isSynthetic = true) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStatementOrigin.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStatementOrigin.kt index 9ee4ebbe248..aa21f49b826 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStatementOrigin.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStatementOrigin.kt @@ -90,7 +90,8 @@ interface IrStatementOrigin { object ANONYMOUS_FUNCTION : IrStatementOriginImpl("ANONYMOUS_FUNCTION") object OBJECT_LITERAL : IrStatementOriginImpl("OBJECT_LITERAL") object ADAPTED_FUNCTION_REFERENCE : IrStatementOriginImpl("ADAPTED_FUNCTION_REFERENCE") - object SUSPEND_CONVERSION: IrStatementOriginImpl("SUSPEND_CONVERSION") + object SUSPEND_CONVERSION : IrStatementOriginImpl("SUSPEND_CONVERSION") + object FUN_INTERFACE_CONSTRUCTOR_REFERENCE : IrStatementOriginImpl("FUN_INTERFACE_CONSTRUCTOR_REFERENCE") object INITIALIZE_PROPERTY_FROM_PARAMETER : IrStatementOriginImpl("INITIALIZE_PROPERTY_FROM_PARAMETER") object INITIALIZE_FIELD : IrStatementOriginImpl("INITIALIZE_FIELD") diff --git a/compiler/testData/ir/irText/expressions/funInterfaceConstructorReference.ir.txt b/compiler/testData/ir/irText/expressions/funInterfaceConstructorReference.ir.txt new file mode 100644 index 00000000000..854135f8234 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/funInterfaceConstructorReference.ir.txt @@ -0,0 +1,128 @@ +FILE fqName: fileName:/funInterfaceConstructorReference.kt + CLASS INTERFACE name:KRunnable modality:ABSTRACT visibility:public [fun] superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.KRunnable + FUN name:run visibility:public modality:ABSTRACT <> ($this:.KRunnable) returnType:kotlin.Unit + $this: VALUE_PARAMETER name: type:.KRunnable + 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 + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + TYPEALIAS name:KR visibility:public expandedType:.KRunnable + CLASS INTERFACE name:KSupplier modality:ABSTRACT visibility:public [fun] superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.KSupplier.KSupplier> + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + FUN name:get visibility:public modality:ABSTRACT <> ($this:.KSupplier.KSupplier>) returnType:T of .KSupplier + $this: VALUE_PARAMETER name: type:.KSupplier.KSupplier> + 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 + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + TYPEALIAS name:KSS visibility:public expandedType:.KSupplier + CLASS INTERFACE name:KConsumer modality:ABSTRACT visibility:public [fun] superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.KConsumer.KConsumer> + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + FUN name:accept visibility:public modality:ABSTRACT <> ($this:.KConsumer.KConsumer>, x:T of .KConsumer) returnType:kotlin.Unit + $this: VALUE_PARAMETER name: type:.KConsumer.KConsumer> + VALUE_PARAMETER name:x index:0 type:T of .KConsumer + 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 + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + TYPEALIAS name:KCS visibility:public expandedType:.KConsumer + FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function0, .KRunnable> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun test1 (): kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function0, .KRunnable> declared in ' + BLOCK type=kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function0, .KRunnable> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE + FUN ADAPTER_FOR_FUN_INTERFACE_CONSTRUCTOR name:KRunnable visibility:local modality:FINAL <> (function:kotlin.Function0) returnType:.KRunnable + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:function index:0 type:kotlin.Function0 + EXPRESSION_BODY + TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable + GET_VAR 'function: kotlin.Function0 declared in .test1.KRunnable' type=kotlin.Function0 origin=null + FUNCTION_REFERENCE 'local final fun KRunnable (function: kotlin.Function0): .KRunnable declared in .test1' type=kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function0, .KRunnable> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE reflectionTarget= + FUN name:test1a visibility:public modality:FINAL <> () returnType:kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function0, .KRunnable> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun test1a (): kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function0, .KRunnable> declared in ' + BLOCK type=kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function0, .KRunnable> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE + FUN ADAPTER_FOR_FUN_INTERFACE_CONSTRUCTOR name:KRunnable visibility:local modality:FINAL <> (function:kotlin.Function0) returnType:.KRunnable + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:function index:0 type:kotlin.Function0 + EXPRESSION_BODY + TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable + GET_VAR 'function: kotlin.Function0 declared in .test1a.KRunnable' type=kotlin.Function0 origin=null + FUNCTION_REFERENCE 'local final fun KRunnable (function: kotlin.Function0): .KRunnable declared in .test1a' type=kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function0, .KRunnable> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE reflectionTarget= + FUN name:test1b visibility:public modality:FINAL <> () returnType:kotlin.reflect.KFunction + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun test1b (): kotlin.reflect.KFunction declared in ' + BLOCK type=kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function0, java.lang.Runnable> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE + FUN ADAPTER_FOR_FUN_INTERFACE_CONSTRUCTOR name:Runnable visibility:local modality:FINAL <> (function:kotlin.Function0) returnType:java.lang.Runnable + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:function index:0 type:kotlin.Function0 + EXPRESSION_BODY + TYPE_OP type=java.lang.Runnable origin=SAM_CONVERSION typeOperand=java.lang.Runnable + GET_VAR 'function: kotlin.Function0 declared in .test1b.Runnable' type=kotlin.Function0 origin=null + FUNCTION_REFERENCE 'local final fun Runnable (function: kotlin.Function0): java.lang.Runnable declared in .test1b' type=kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function0, java.lang.Runnable> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE reflectionTarget= + FUN name:test2 visibility:public modality:FINAL <> () returnType:kotlin.Function1, .KSupplier> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun test2 (): kotlin.Function1, .KSupplier> declared in ' + BLOCK type=kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function0, .KSupplier> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE + FUN ADAPTER_FOR_FUN_INTERFACE_CONSTRUCTOR name:KSupplier visibility:local modality:FINAL <> (function:kotlin.Function0) returnType:.KSupplier + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:function index:0 type:kotlin.Function0 + EXPRESSION_BODY + TYPE_OP type=.KSupplier origin=SAM_CONVERSION typeOperand=.KSupplier + GET_VAR 'function: kotlin.Function0 declared in .test2.KSupplier' type=kotlin.Function0 origin=null + FUNCTION_REFERENCE 'local final fun KSupplier (function: kotlin.Function0): .KSupplier declared in .test2' type=kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function0, .KSupplier> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE reflectionTarget= + FUN name:test2a visibility:public modality:FINAL <> () returnType:kotlin.Function1, .KSupplier> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun test2a (): kotlin.Function1, .KSupplier> declared in ' + BLOCK type=kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function0, .KSupplier> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE + FUN ADAPTER_FOR_FUN_INTERFACE_CONSTRUCTOR name:KSupplier visibility:local modality:FINAL <> (function:kotlin.Function0) returnType:.KSupplier + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:function index:0 type:kotlin.Function0 + EXPRESSION_BODY + TYPE_OP type=.KSupplier origin=SAM_CONVERSION typeOperand=.KSupplier + GET_VAR 'function: kotlin.Function0 declared in .test2a.KSupplier' type=kotlin.Function0 origin=null + FUNCTION_REFERENCE 'local final fun KSupplier (function: kotlin.Function0): .KSupplier declared in .test2a' type=kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function0, .KSupplier> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE reflectionTarget= + FUN name:test3 visibility:public modality:FINAL <> () returnType:kotlin.Function1, .KConsumer> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun test3 (): kotlin.Function1, .KConsumer> declared in ' + BLOCK type=kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String, kotlin.Unit>, .KConsumer> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE + FUN ADAPTER_FOR_FUN_INTERFACE_CONSTRUCTOR name:KConsumer visibility:local modality:FINAL <> (function:kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String, kotlin.Unit>) returnType:.KConsumer + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:function index:0 type:kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String, kotlin.Unit> + EXPRESSION_BODY + TYPE_OP type=.KConsumer origin=SAM_CONVERSION typeOperand=.KConsumer + GET_VAR 'function: kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String, kotlin.Unit> declared in .test3.KConsumer' type=kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String, kotlin.Unit> origin=null + FUNCTION_REFERENCE 'local final fun KConsumer (function: kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String, kotlin.Unit>): .KConsumer declared in .test3' type=kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String, kotlin.Unit>, .KConsumer> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE reflectionTarget= + FUN name:test3a visibility:public modality:FINAL <> () returnType:kotlin.Function1, .KConsumer> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun test3a (): kotlin.Function1, .KConsumer> declared in ' + BLOCK type=kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String, kotlin.Unit>, .KConsumer> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE + FUN ADAPTER_FOR_FUN_INTERFACE_CONSTRUCTOR name:KConsumer visibility:local modality:FINAL <> (function:kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String, kotlin.Unit>) returnType:.KConsumer + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:function index:0 type:kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String, kotlin.Unit> + EXPRESSION_BODY + TYPE_OP type=.KConsumer origin=SAM_CONVERSION typeOperand=.KConsumer + GET_VAR 'function: kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String, kotlin.Unit> declared in .test3a.KConsumer' type=kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String, kotlin.Unit> origin=null + FUNCTION_REFERENCE 'local final fun KConsumer (function: kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String, kotlin.Unit>): .KConsumer declared in .test3a' type=kotlin.reflect.KFunction1<@[ParameterName(name = 'function')] kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String, kotlin.Unit>, .KConsumer> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE reflectionTarget= diff --git a/compiler/testData/ir/irText/expressions/funInterfaceConstructorReference.kt b/compiler/testData/ir/irText/expressions/funInterfaceConstructorReference.kt new file mode 100644 index 00000000000..476dbf728a5 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/funInterfaceConstructorReference.kt @@ -0,0 +1,36 @@ +// !LANGUAGE: +AllowKotlinFunInterfaceConstructorReference +// WITH_REFLECT +import kotlin.reflect.* + +fun interface KRunnable { + fun run() +} + +typealias KR = KRunnable + +fun interface KSupplier { + fun get(): T +} + +typealias KSS = KSupplier + +fun interface KConsumer { + fun accept(x: T) +} + +typealias KCS = KConsumer + +fun test1() = ::KRunnable + +fun test1a() = ::KR + +fun test1b(): KFunction = ::Runnable + +fun test2(): (() -> String) -> KSupplier = ::KSupplier + +fun test2a(): (() -> String) -> KSupplier = ::KSS + +fun test3(): ((String) -> Unit) -> KConsumer = ::KConsumer + +fun test3a(): ((String) -> Unit) -> KConsumer = ::KCS + diff --git a/compiler/testData/ir/irText/expressions/funInterfaceConstructorReference.kt.txt b/compiler/testData/ir/irText/expressions/funInterfaceConstructorReference.kt.txt new file mode 100644 index 00000000000..af71f6aaf7b --- /dev/null +++ b/compiler/testData/ir/irText/expressions/funInterfaceConstructorReference.kt.txt @@ -0,0 +1,74 @@ +fun interface KRunnable { + abstract fun run() + +} + +typealias KR = KRunnable +fun interface KSupplier { + abstract fun get(): T + +} + +typealias KSS = KSupplier +fun interface KConsumer { + abstract fun accept(x: T) + +} + +typealias KCS = KConsumer +fun test1(): KFunction1<@ParameterName(name = "function") Function0, KRunnable> { + return { // BLOCK + local fun KRunnable(fn: Function0): KRunnable fn /*-> KRunnable */ + + ::KRunnable + } +} + +fun test1a(): KFunction1<@ParameterName(name = "function") Function0, KRunnable> { + return { // BLOCK + local fun KRunnable(fn: Function0): KRunnable fn /*-> KRunnable */ + + ::KRunnable + } +} + +fun test1b(): KFunction { + return { // BLOCK + local fun Runnable(fn: Function0): Runnable fn /*-> Runnable */ + + ::Runnable + } +} + +fun test2(): Function1, KSupplier> { + return { // BLOCK + local fun KSupplier(fn: Function0): KSupplier fn /*-> KSupplier */ + + ::KSupplier + } +} + +fun test2a(): Function1, KSupplier> { + return { // BLOCK + local fun KSupplier(fn: Function0): KSupplier fn /*-> KSupplier */ + + ::KSupplier + } +} + +fun test3(): Function1, KConsumer> { + return { // BLOCK + local fun KConsumer(fn: Function1<@ParameterName(name = "x") String, Unit>): KConsumer fn /*-> KConsumer */ + + ::KConsumer + } +} + +fun test3a(): Function1, KConsumer> { + return { // BLOCK + local fun KConsumer(fn: Function1<@ParameterName(name = "x") String, Unit>): KConsumer fn /*-> KConsumer */ + + ::KConsumer + } +} + diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java index 44a75bb7321..82095560154 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java @@ -1394,6 +1394,12 @@ public class IrTextTestGenerated extends AbstractIrTextTest { runTest("compiler/testData/ir/irText/expressions/funImportedFromObject.kt"); } + @Test + @TestMetadata("funInterfaceConstructorReference.kt") + public void testFunInterfaceConstructorReference() throws Exception { + runTest("compiler/testData/ir/irText/expressions/funInterfaceConstructorReference.kt"); + } + @Test @TestMetadata("genericConstructorCallWithTypeArguments.kt") public void testGenericConstructorCallWithTypeArguments() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/ir/KlibTextTestCaseGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/ir/KlibTextTestCaseGenerated.java index 7fb5f5734d9..6266cc4403e 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/ir/KlibTextTestCaseGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/ir/KlibTextTestCaseGenerated.java @@ -1077,6 +1077,11 @@ public class KlibTextTestCaseGenerated extends AbstractKlibTextTestCase { runTest("compiler/testData/ir/irText/expressions/funImportedFromObject.kt"); } + @TestMetadata("funInterfaceConstructorReference.kt") + public void testFunInterfaceConstructorReference() throws Exception { + runTest("compiler/testData/ir/irText/expressions/funInterfaceConstructorReference.kt"); + } + @TestMetadata("genericConstructorCallWithTypeArguments.kt") public void testGenericConstructorCallWithTypeArguments() throws Exception { runTest("compiler/testData/ir/irText/expressions/genericConstructorCallWithTypeArguments.kt");