From eebb071ae90f3afb4fecd22d36245269b513609f Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Mon, 21 Oct 2019 16:01:33 +0300 Subject: [PATCH] KT-34509 Properly unwrap callable reference descriptor NB there's a problem with callable references to SAM constructors, see also KT-16789 --- .../kotlin/fir/Fir2IrTextTestGenerated.java | 5 ++ .../ReflectionReferencesGenerator.kt | 12 ++- .../typeAliasConstructorReference.fir.txt | 78 ++++++++++++++++++ .../typeAliasConstructorReference.kt | 14 ++++ .../typeAliasConstructorReference.txt | 80 +++++++++++++++++++ .../kotlin/ir/IrTextTestCaseGenerated.java | 5 ++ 6 files changed, 187 insertions(+), 7 deletions(-) create mode 100644 compiler/testData/ir/irText/expressions/typeAliasConstructorReference.fir.txt create mode 100644 compiler/testData/ir/irText/expressions/typeAliasConstructorReference.kt create mode 100644 compiler/testData/ir/irText/expressions/typeAliasConstructorReference.txt diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java index 5ed1fc3f327..27688b234eb 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java @@ -1212,6 +1212,11 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest { runTest("compiler/testData/ir/irText/expressions/tryCatchWithImplicitCast.kt"); } + @TestMetadata("typeAliasConstructorReference.kt") + public void testTypeAliasConstructorReference() throws Exception { + runTest("compiler/testData/ir/irText/expressions/typeAliasConstructorReference.kt"); + } + @TestMetadata("typeArguments.kt") public void testTypeArguments() throws Exception { runTest("compiler/testData/ir/irText/expressions/typeArguments.kt"); 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 46ca1bd6376..41a004b95c7 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 @@ -29,7 +29,6 @@ import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.expressions.DoubleColonLHS @@ -58,22 +57,21 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St fun generateCallableReference(ktCallableReference: KtCallableReferenceExpression): IrExpression { val resolvedCall = getResolvedCall(ktCallableReference.callableReference)!! + val resolvedDescriptor = resolvedCall.resultingDescriptor - val resultingDescriptor = resolvedCall.resultingDescriptor - val descriptorImportedFromObject = resultingDescriptor as? ImportedFromObjectCallableDescriptor<*> - val referencedDescriptor = descriptorImportedFromObject?.callableFromObject ?: resultingDescriptor + val callBuilder = unwrapCallableDescriptorAndTypeArguments(resolvedCall, context.extensions.samConversion) return statementGenerator.generateCallReceiver( ktCallableReference, - resultingDescriptor, + resolvedDescriptor, resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver, isSafe = false ).call { dispatchReceiverValue, extensionReceiverValue -> generateCallableReference( ktCallableReference, getInferredTypeWithImplicitCastsOrFail(ktCallableReference), - referencedDescriptor, - resolvedCall.typeArguments + callBuilder.descriptor, + callBuilder.typeArguments ).also { irCallableReference -> irCallableReference.dispatchReceiver = dispatchReceiverValue?.loadIfExists() irCallableReference.extensionReceiver = extensionReceiverValue?.loadIfExists() diff --git a/compiler/testData/ir/irText/expressions/typeAliasConstructorReference.fir.txt b/compiler/testData/ir/irText/expressions/typeAliasConstructorReference.fir.txt new file mode 100644 index 00000000000..0268172b8df --- /dev/null +++ b/compiler/testData/ir/irText/expressions/typeAliasConstructorReference.fir.txt @@ -0,0 +1,78 @@ +FILE fqName: fileName:/typeAliasConstructorReference.kt + CLASS CLASS name:C modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.C + CONSTRUCTOR visibility:public <> (x:kotlin.Int) returnType:.C [primary] + VALUE_PARAMETER name:x index:0 type:kotlin.Int + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:C modality:FINAL visibility:public superTypes:[kotlin.Any]' + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean 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 + 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 + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS OBJECT name:Host modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Host + CONSTRUCTOR visibility:private <> () returnType:.Host [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS OBJECT name:Host modality:FINAL visibility:public superTypes:[kotlin.Any]' + CLASS CLASS name:Nested modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Host.Nested + CONSTRUCTOR visibility:public <> (x:kotlin.Int) returnType:.Host.Nested [primary] + VALUE_PARAMETER name:x index:0 type:kotlin.Int + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Nested modality:FINAL visibility:public superTypes:[kotlin.Any]' + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean 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 + 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 + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean 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 + 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 + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + PROPERTY name:test1 visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Function1.C> visibility:private [final,static] + EXPRESSION_BODY + GET_OBJECT 'CLASS CLASS name:C modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Function1.C> + correspondingProperty: PROPERTY name:test1 visibility:public modality:FINAL [val] + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Function1.C> declared in ' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Function1.C> visibility:private [final,static]' type=kotlin.Function1.C> origin=null + PROPERTY name:test2 visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Function1.Host.Nested> visibility:private [final,static] + EXPRESSION_BODY + GET_OBJECT 'CLASS CLASS name:Nested modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Function1.Host.Nested> + correspondingProperty: PROPERTY name:test2 visibility:public modality:FINAL [val] + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Function1.Host.Nested> declared in ' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Function1.Host.Nested> visibility:private [final,static]' type=kotlin.Function1.Host.Nested> origin=null diff --git a/compiler/testData/ir/irText/expressions/typeAliasConstructorReference.kt b/compiler/testData/ir/irText/expressions/typeAliasConstructorReference.kt new file mode 100644 index 00000000000..91d00c524d7 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/typeAliasConstructorReference.kt @@ -0,0 +1,14 @@ +import Host.Nested + +class C(x: Int) + +typealias CA = C + +object Host { + class Nested(x: Int) +} + +typealias NA = Nested + +val test1: (Int) -> CA = ::CA +val test2: (Int) -> NA = ::NA \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/typeAliasConstructorReference.txt b/compiler/testData/ir/irText/expressions/typeAliasConstructorReference.txt new file mode 100644 index 00000000000..c1166cfc40f --- /dev/null +++ b/compiler/testData/ir/irText/expressions/typeAliasConstructorReference.txt @@ -0,0 +1,80 @@ +FILE fqName: fileName:/typeAliasConstructorReference.kt + CLASS CLASS name:C modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.C + CONSTRUCTOR visibility:public <> (x:kotlin.Int) returnType:.C [primary] + VALUE_PARAMETER name:x index:0 type:kotlin.Int + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:C modality:FINAL visibility:public superTypes:[kotlin.Any]' + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean 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 + 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 + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + TYPEALIAS name:CA visibility:public expandedType:.C + CLASS OBJECT name:Host modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Host + CONSTRUCTOR visibility:private <> () returnType:.Host [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS OBJECT name:Host modality:FINAL visibility:public superTypes:[kotlin.Any]' + CLASS CLASS name:Nested modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Host.Nested + CONSTRUCTOR visibility:public <> (x:kotlin.Int) returnType:.Host.Nested [primary] + VALUE_PARAMETER name:x index:0 type:kotlin.Int + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Nested modality:FINAL visibility:public superTypes:[kotlin.Any]' + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean 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 + 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 + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean 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 + 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 + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + TYPEALIAS name:NA visibility:public expandedType:.Host.Nested + PROPERTY name:test1 visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Function1.C{ .CA }> visibility:private [final,static] + EXPRESSION_BODY + FUNCTION_REFERENCE 'public constructor (x: kotlin.Int) [primary] declared in .C' type=kotlin.reflect.KFunction1<@[ParameterName(name = 'x')] kotlin.Int, .C{ .CA }> origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Function1.C{ .CA }> + correspondingProperty: PROPERTY name:test1 visibility:public modality:FINAL [val] + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Function1.C{ .CA }> declared in ' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Function1.C{ .CA }> visibility:private [final,static]' type=kotlin.Function1.C{ .CA }> origin=null + PROPERTY name:test2 visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Function1.Host.Nested{ .NA }> visibility:private [final,static] + EXPRESSION_BODY + FUNCTION_REFERENCE 'public constructor (x: kotlin.Int) [primary] declared in .Host.Nested' type=kotlin.reflect.KFunction1<@[ParameterName(name = 'x')] kotlin.Int, .Host.Nested{ .NA }> origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Function1.Host.Nested{ .NA }> + correspondingProperty: PROPERTY name:test2 visibility:public modality:FINAL [val] + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Function1.Host.Nested{ .NA }> declared in ' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Function1.Host.Nested{ .NA }> visibility:private [final,static]' type=kotlin.Function1.Host.Nested{ .NA }> origin=null diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index d4719ca4212..71a72b77ef2 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -1212,6 +1212,11 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { runTest("compiler/testData/ir/irText/expressions/tryCatchWithImplicitCast.kt"); } + @TestMetadata("typeAliasConstructorReference.kt") + public void testTypeAliasConstructorReference() throws Exception { + runTest("compiler/testData/ir/irText/expressions/typeAliasConstructorReference.kt"); + } + @TestMetadata("typeArguments.kt") public void testTypeArguments() throws Exception { runTest("compiler/testData/ir/irText/expressions/typeArguments.kt");