From bd9c5645cdca4e4742652a27255d3670b90aab33 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Thu, 28 Feb 2019 15:30:30 +0300 Subject: [PATCH] IR: fix property reference symbol binding for generic properties --- .../ReflectionReferencesGenerator.kt | 11 +- .../irText/expressions/genericPropertyRef.kt | 18 ++ .../irText/expressions/genericPropertyRef.txt | 195 ++++++++++++++++++ .../kotlin/ir/IrTextTestCaseGenerated.java | 5 + 4 files changed, 224 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/ir/irText/expressions/genericPropertyRef.kt create mode 100644 compiler/testData/ir/irText/expressions/genericPropertyRef.txt 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 915881082a6..0417e3404a9 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 @@ -136,16 +136,17 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St origin: IrStatementOrigin?, mutable: Boolean ): IrPropertyReference { - val getterDescriptor = propertyDescriptor.getter - val setterDescriptor = if (mutable) propertyDescriptor.setter else null + val originalProperty = propertyDescriptor.original + val originalGetter = originalProperty.getter?.original + val originalSetter = if (mutable) originalProperty.setter?.original else null return IrPropertyReferenceImpl( startOffset, endOffset, type.toIrType(), context.symbolTable.referenceProperty(propertyDescriptor.original), propertyDescriptor.typeParametersCount, - getterDescriptor?.run { context.symbolTable.referenceField(propertyDescriptor) }, - getterDescriptor?.let { context.symbolTable.referenceSimpleFunction(it.original) }, - setterDescriptor?.let { context.symbolTable.referenceSimpleFunction(it.original) }, + originalGetter?.run { context.symbolTable.referenceField(originalProperty) }, + originalGetter?.let { context.symbolTable.referenceSimpleFunction(it) }, + originalSetter?.let { context.symbolTable.referenceSimpleFunction(it) }, origin ).apply { putTypeArguments(typeArguments) { it.toIrType() } diff --git a/compiler/testData/ir/irText/expressions/genericPropertyRef.kt b/compiler/testData/ir/irText/expressions/genericPropertyRef.kt new file mode 100644 index 00000000000..8deacf03548 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/genericPropertyRef.kt @@ -0,0 +1,18 @@ +class Value(var value: T = null as T, var text: String? = null) + +val Value.additionalText by DVal(Value::text) + +val Value.additionalValue by DVal(Value::value) + +class DVal(val kmember: Any) { + operator fun getValue(t: Any?, p: Any) = 42 +} + +var recivier : Any? = "fail" +var value2 : Any? = "fail2" + +var T.bar : T + get() = this + set(value) { recivier = this; value2 = value} + +val barRef = String?::bar \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/genericPropertyRef.txt b/compiler/testData/ir/irText/expressions/genericPropertyRef.txt new file mode 100644 index 00000000000..0383b5ff4f2 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/genericPropertyRef.txt @@ -0,0 +1,195 @@ +FILE fqName: fileName:/genericPropertyRef.kt + CLASS CLASS name:Value modality:FINAL visibility:public flags: superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:Value flags: + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + CONSTRUCTOR visibility:public <> (value:T, text:kotlin.String?) returnType:Value flags:primary + VALUE_PARAMETER name:value index:0 type:T flags: + EXPRESSION_BODY + TYPE_OP type=T origin=CAST typeOperand=T + typeOperand: TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + CONST Null type=kotlin.Nothing? value=null + VALUE_PARAMETER name:text index:1 type:kotlin.String? flags: + EXPRESSION_BODY + CONST Null type=kotlin.Nothing? value=null + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'constructor Any()' + INSTANCE_INITIALIZER_CALL classDescriptor='Value' + PROPERTY name:value visibility:public modality:FINAL flags:var + FIELD PROPERTY_BACKING_FIELD name:value type:T visibility:public flags: + EXPRESSION_BODY + GET_VAR 'value-parameter value: T = ...' type=T origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:Value) returnType:T flags: + correspondingProperty: PROPERTY name:value visibility:public modality:FINAL flags:var + $this: VALUE_PARAMETER name: type:Value flags: + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): T' + GET_FIELD 'value: T' type=T origin=null + receiver: GET_VAR 'this@Value: Value' type=Value origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:Value, :T) returnType:kotlin.Unit flags: + correspondingProperty: PROPERTY name:value visibility:public modality:FINAL flags:var + $this: VALUE_PARAMETER name: type:Value flags: + VALUE_PARAMETER name: index:0 type:T flags: + BLOCK_BODY + SET_FIELD 'value: T' type=kotlin.Unit origin=null + receiver: GET_VAR 'this@Value: Value' type=Value origin=null + value: GET_VAR 'value-parameter : T' type=T origin=null + PROPERTY name:text visibility:public modality:FINAL flags:var + FIELD PROPERTY_BACKING_FIELD name:text type:kotlin.String? visibility:public flags: + EXPRESSION_BODY + GET_VAR 'value-parameter text: String? = ...' type=kotlin.String? origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:Value) returnType:kotlin.String? flags: + correspondingProperty: PROPERTY name:text visibility:public modality:FINAL flags:var + $this: VALUE_PARAMETER name: type:Value flags: + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): String?' + GET_FIELD 'text: String?' type=kotlin.String? origin=null + receiver: GET_VAR 'this@Value: Value' type=Value origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:Value, :kotlin.String?) returnType:kotlin.Unit flags: + correspondingProperty: PROPERTY name:text visibility:public modality:FINAL flags:var + $this: VALUE_PARAMETER name: type:Value flags: + VALUE_PARAMETER name: index:0 type:kotlin.String? flags: + BLOCK_BODY + SET_FIELD 'text: String?' type=kotlin.Unit origin=null + receiver: GET_VAR 'this@Value: Value' type=Value origin=null + value: GET_VAR 'value-parameter : String?' type=kotlin.String? origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags: + overridden: + FUN IR_EXTERNAL_DECLARATION_STUB name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + VALUE_PARAMETER name:other index:0 type:kotlin.Any? flags: + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags: + overridden: + FUN IR_EXTERNAL_DECLARATION_STUB name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags: + overridden: + FUN IR_EXTERNAL_DECLARATION_STUB name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + PROPERTY name:additionalText visibility:public modality:FINAL flags:delegated,val + FIELD DELEGATE name:additionalText$delegate type:DVal visibility:private flags:final,static + EXPRESSION_BODY + CALL 'constructor DVal(Any)' type=DVal origin=null + kmember: PROPERTY_REFERENCE 'text: String?' field='text: String?' getter='(): String?' setter='(String?): Unit' type=kotlin.reflect.KMutableProperty1, kotlin.String?> origin=null + FUN DELEGATED_PROPERTY_ACCESSOR name: visibility:public modality:FINAL ($receiver:Value) returnType:kotlin.Int flags: + correspondingProperty: PROPERTY name:additionalText visibility:public modality:FINAL flags:delegated,val + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + $receiver: VALUE_PARAMETER name: type:Value flags: + BLOCK_BODY + RETURN type=kotlin.Nothing from='() on Value: Int' + CALL 'getValue(Any?, Any): Int' type=kotlin.Int origin=null + $this: GET_FIELD '`additionalText$delegate`: DVal' type=DVal origin=null + t: GET_VAR 'this@additionalText: Value' type=Value origin=null + p: PROPERTY_REFERENCE 'additionalText: Int on Value' field='additionalText: Int on Value' getter='() on Value: Int' setter=null type=kotlin.reflect.KProperty1, kotlin.Int> origin=PROPERTY_REFERENCE_FOR_DELEGATE + : + PROPERTY name:additionalValue visibility:public modality:FINAL flags:delegated,val + FIELD DELEGATE name:additionalValue$delegate type:DVal visibility:private flags:final,static + EXPRESSION_BODY + CALL 'constructor DVal(Any)' type=DVal origin=null + kmember: PROPERTY_REFERENCE 'value: T' field='value: T' getter='(): T' setter='(T): Unit' type=kotlin.reflect.KMutableProperty1, T> origin=null + FUN DELEGATED_PROPERTY_ACCESSOR name: visibility:public modality:FINAL ($receiver:Value) returnType:kotlin.Int flags: + correspondingProperty: PROPERTY name:additionalValue visibility:public modality:FINAL flags:delegated,val + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + $receiver: VALUE_PARAMETER name: type:Value flags: + BLOCK_BODY + RETURN type=kotlin.Nothing from='() on Value: Int' + CALL 'getValue(Any?, Any): Int' type=kotlin.Int origin=null + $this: GET_FIELD '`additionalValue$delegate`: DVal' type=DVal origin=null + t: GET_VAR 'this@additionalValue: Value' type=Value origin=null + p: PROPERTY_REFERENCE 'additionalValue: Int on Value' field='additionalValue: Int on Value' getter='() on Value: Int' setter=null type=kotlin.reflect.KProperty1, kotlin.Int> origin=PROPERTY_REFERENCE_FOR_DELEGATE + : + CLASS CLASS name:DVal modality:FINAL visibility:public flags: superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:DVal flags: + CONSTRUCTOR visibility:public <> (kmember:kotlin.Any) returnType:DVal flags:primary + VALUE_PARAMETER name:kmember index:0 type:kotlin.Any flags: + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'constructor Any()' + INSTANCE_INITIALIZER_CALL classDescriptor='DVal' + PROPERTY name:kmember visibility:public modality:FINAL flags:val + FIELD PROPERTY_BACKING_FIELD name:kmember type:kotlin.Any visibility:public flags:final + EXPRESSION_BODY + GET_VAR 'value-parameter kmember: Any' type=kotlin.Any origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:DVal) returnType:kotlin.Any flags: + correspondingProperty: PROPERTY name:kmember visibility:public modality:FINAL flags:val + $this: VALUE_PARAMETER name: type:DVal flags: + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Any' + GET_FIELD 'kmember: Any' type=kotlin.Any origin=null + receiver: GET_VAR 'this@DVal: DVal' type=DVal origin=null + FUN name:getValue visibility:public modality:FINAL <> ($this:DVal, t:kotlin.Any?, p:kotlin.Any) returnType:kotlin.Int flags: + $this: VALUE_PARAMETER name: type:DVal flags: + VALUE_PARAMETER name:t index:0 type:kotlin.Any? flags: + VALUE_PARAMETER name:p index:1 type:kotlin.Any flags: + BLOCK_BODY + RETURN type=kotlin.Nothing from='getValue(Any?, Any): Int' + CONST Int type=kotlin.Int value=42 + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags: + overridden: + FUN IR_EXTERNAL_DECLARATION_STUB name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + VALUE_PARAMETER name:other index:0 type:kotlin.Any? flags: + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags: + overridden: + FUN IR_EXTERNAL_DECLARATION_STUB name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags: + overridden: + FUN IR_EXTERNAL_DECLARATION_STUB name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + PROPERTY name:recivier visibility:public modality:FINAL flags:var + FIELD PROPERTY_BACKING_FIELD name:recivier type:kotlin.Any? visibility:public flags:static + EXPRESSION_BODY + CONST String type=kotlin.String value="fail" + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Any? flags: + correspondingProperty: PROPERTY name:recivier visibility:public modality:FINAL flags:var + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Any?' + GET_FIELD 'recivier: Any?' type=kotlin.Any? origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> (:kotlin.Any?) returnType:kotlin.Unit flags: + correspondingProperty: PROPERTY name:recivier visibility:public modality:FINAL flags:var + VALUE_PARAMETER name: index:0 type:kotlin.Any? flags: + BLOCK_BODY + SET_FIELD 'recivier: Any?' type=kotlin.Unit origin=null + value: GET_VAR 'value-parameter : Any?' type=kotlin.Any? origin=null + PROPERTY name:value2 visibility:public modality:FINAL flags:var + FIELD PROPERTY_BACKING_FIELD name:value2 type:kotlin.Any? visibility:public flags:static + EXPRESSION_BODY + CONST String type=kotlin.String value="fail2" + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Any? flags: + correspondingProperty: PROPERTY name:value2 visibility:public modality:FINAL flags:var + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Any?' + GET_FIELD 'value2: Any?' type=kotlin.Any? origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> (:kotlin.Any?) returnType:kotlin.Unit flags: + correspondingProperty: PROPERTY name:value2 visibility:public modality:FINAL flags:var + VALUE_PARAMETER name: index:0 type:kotlin.Any? flags: + BLOCK_BODY + SET_FIELD 'value2: Any?' type=kotlin.Unit origin=null + value: GET_VAR 'value-parameter : Any?' type=kotlin.Any? origin=null + PROPERTY name:bar visibility:public modality:FINAL flags:var + FUN name: visibility:public modality:FINAL ($receiver:T) returnType:T flags: + correspondingProperty: PROPERTY name:bar visibility:public modality:FINAL flags:var + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + $receiver: VALUE_PARAMETER name: type:T flags: + BLOCK_BODY + RETURN type=kotlin.Nothing from='() on T: T' + GET_VAR 'this@bar: T' type=T origin=null + FUN name: visibility:public modality:FINAL ($receiver:T, value:T) returnType:kotlin.Unit flags: + correspondingProperty: PROPERTY name:bar visibility:public modality:FINAL flags:var + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + $receiver: VALUE_PARAMETER name: type:T flags: + VALUE_PARAMETER name:value index:0 type:T flags: + BLOCK_BODY + CALL '(Any?): Unit' type=kotlin.Unit origin=EQ + : GET_VAR 'this@bar: T' type=T origin=null + CALL '(Any?): Unit' type=kotlin.Unit origin=EQ + : GET_VAR 'value-parameter value: T' type=T origin=null + PROPERTY name:barRef visibility:public modality:FINAL flags:val + FIELD PROPERTY_BACKING_FIELD name:barRef type:kotlin.reflect.KMutableProperty1 visibility:public flags:final,static + EXPRESSION_BODY + PROPERTY_REFERENCE 'bar: T on T' field='bar: T on T' getter='() on T: T' setter='(T) on T: Unit' type=kotlin.reflect.KMutableProperty1 origin=null + : kotlin.String? + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.reflect.KMutableProperty1 flags: + correspondingProperty: PROPERTY name:barRef visibility:public modality:FINAL flags:val + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): KMutableProperty1' + GET_FIELD 'barRef: KMutableProperty1' type=kotlin.reflect.KMutableProperty1 origin=null diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index 9db9c1d7bfa..31720563bf6 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -887,6 +887,11 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { runTest("compiler/testData/ir/irText/expressions/genericPropertyCall.kt"); } + @TestMetadata("genericPropertyRef.kt") + public void testGenericPropertyRef() throws Exception { + runTest("compiler/testData/ir/irText/expressions/genericPropertyRef.kt"); + } + @TestMetadata("identity.kt") public void testIdentity() throws Exception { runTest("compiler/testData/ir/irText/expressions/identity.kt");