IR: fix property reference symbol binding for generic properties

This commit is contained in:
Dmitry Petrov
2019-02-28 15:30:30 +03:00
parent 8b4dab7c25
commit bd9c5645cd
4 changed files with 224 additions and 5 deletions
@@ -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() }
@@ -0,0 +1,18 @@
class Value<T>(var value: T = null as T, var text: String? = null)
val <T> Value<T>.additionalText by DVal(Value<T>::text)
val <T> Value<T>.additionalValue by DVal(Value<T>::value)
class DVal(val kmember: Any) {
operator fun getValue(t: Any?, p: Any) = 42
}
var recivier : Any? = "fail"
var value2 : Any? = "fail2"
var <T> T.bar : T
get() = this
set(value) { recivier = this; value2 = value}
val barRef = String?::bar
@@ -0,0 +1,195 @@
FILE fqName:<root> fileName:/genericPropertyRef.kt
CLASS CLASS name:Value modality:FINAL visibility:public flags: superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:Value<T> flags:
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
CONSTRUCTOR visibility:public <> (value:T, text:kotlin.String?) returnType:Value<T> 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:<get-value> visibility:public modality:FINAL <> ($this:Value<T>) returnType:T flags:
correspondingProperty: PROPERTY name:value visibility:public modality:FINAL flags:var
$this: VALUE_PARAMETER name:<this> type:Value<T> flags:
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-value>(): T'
GET_FIELD 'value: T' type=T origin=null
receiver: GET_VAR 'this@Value: Value<T>' type=Value<T> origin=null
FUN DEFAULT_PROPERTY_ACCESSOR name:<set-value> visibility:public modality:FINAL <> ($this:Value<T>, <set-?>:T) returnType:kotlin.Unit flags:
correspondingProperty: PROPERTY name:value visibility:public modality:FINAL flags:var
$this: VALUE_PARAMETER name:<this> type:Value<T> flags:
VALUE_PARAMETER name:<set-?> index:0 type:T flags:
BLOCK_BODY
SET_FIELD 'value: T' type=kotlin.Unit origin=null
receiver: GET_VAR 'this@Value: Value<T>' type=Value<T> origin=null
value: GET_VAR 'value-parameter <set-?>: 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:<get-text> visibility:public modality:FINAL <> ($this:Value<T>) returnType:kotlin.String? flags:
correspondingProperty: PROPERTY name:text visibility:public modality:FINAL flags:var
$this: VALUE_PARAMETER name:<this> type:Value<T> flags:
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-text>(): String?'
GET_FIELD 'text: String?' type=kotlin.String? origin=null
receiver: GET_VAR 'this@Value: Value<T>' type=Value<T> origin=null
FUN DEFAULT_PROPERTY_ACCESSOR name:<set-text> visibility:public modality:FINAL <> ($this:Value<T>, <set-?>:kotlin.String?) returnType:kotlin.Unit flags:
correspondingProperty: PROPERTY name:text visibility:public modality:FINAL flags:var
$this: VALUE_PARAMETER name:<this> type:Value<T> flags:
VALUE_PARAMETER name:<set-?> index:0 type:kotlin.String? flags:
BLOCK_BODY
SET_FIELD 'text: String?' type=kotlin.Unit origin=null
receiver: GET_VAR 'this@Value: Value<T>' type=Value<T> origin=null
value: GET_VAR 'value-parameter <set-?>: 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:<this> 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:<this> 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:<this> 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='<get-text>(): String?' setter='<set-text>(String?): Unit' type=kotlin.reflect.KMutableProperty1<Value<T>, kotlin.String?> origin=null
FUN DELEGATED_PROPERTY_ACCESSOR name:<get-additionalText> visibility:public modality:FINAL <T> ($receiver:Value<T>) 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:<this> type:Value<T> flags:
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-additionalText>() on Value<T>: 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<T>' type=Value<T> origin=null
p: PROPERTY_REFERENCE 'additionalText: Int on Value<T>' field='additionalText: Int on Value<T>' getter='<get-additionalText>() on Value<T>: Int' setter=null type=kotlin.reflect.KProperty1<Value<T>, kotlin.Int> origin=PROPERTY_REFERENCE_FOR_DELEGATE
<T>: <none>
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='<get-value>(): T' setter='<set-value>(T): Unit' type=kotlin.reflect.KMutableProperty1<Value<T>, T> origin=null
FUN DELEGATED_PROPERTY_ACCESSOR name:<get-additionalValue> visibility:public modality:FINAL <T> ($receiver:Value<T>) 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:<this> type:Value<T> flags:
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-additionalValue>() on Value<T>: 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<T>' type=Value<T> origin=null
p: PROPERTY_REFERENCE 'additionalValue: Int on Value<T>' field='additionalValue: Int on Value<T>' getter='<get-additionalValue>() on Value<T>: Int' setter=null type=kotlin.reflect.KProperty1<Value<T>, kotlin.Int> origin=PROPERTY_REFERENCE_FOR_DELEGATE
<T>: <none>
CLASS CLASS name:DVal modality:FINAL visibility:public flags: superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> 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:<get-kmember> visibility:public modality:FINAL <> ($this:DVal) returnType:kotlin.Any flags:
correspondingProperty: PROPERTY name:kmember visibility:public modality:FINAL flags:val
$this: VALUE_PARAMETER name:<this> type:DVal flags:
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-kmember>(): 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:<this> 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:<this> 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:<this> 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:<this> 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:<get-recivier> 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='<get-recivier>(): Any?'
GET_FIELD 'recivier: Any?' type=kotlin.Any? origin=null
FUN DEFAULT_PROPERTY_ACCESSOR name:<set-recivier> visibility:public modality:FINAL <> (<set-?>:kotlin.Any?) returnType:kotlin.Unit flags:
correspondingProperty: PROPERTY name:recivier visibility:public modality:FINAL flags:var
VALUE_PARAMETER name:<set-?> index:0 type:kotlin.Any? flags:
BLOCK_BODY
SET_FIELD 'recivier: Any?' type=kotlin.Unit origin=null
value: GET_VAR 'value-parameter <set-?>: 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:<get-value2> 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='<get-value2>(): Any?'
GET_FIELD 'value2: Any?' type=kotlin.Any? origin=null
FUN DEFAULT_PROPERTY_ACCESSOR name:<set-value2> visibility:public modality:FINAL <> (<set-?>:kotlin.Any?) returnType:kotlin.Unit flags:
correspondingProperty: PROPERTY name:value2 visibility:public modality:FINAL flags:var
VALUE_PARAMETER name:<set-?> index:0 type:kotlin.Any? flags:
BLOCK_BODY
SET_FIELD 'value2: Any?' type=kotlin.Unit origin=null
value: GET_VAR 'value-parameter <set-?>: Any?' type=kotlin.Any? origin=null
PROPERTY name:bar visibility:public modality:FINAL flags:var
FUN name:<get-bar> visibility:public modality:FINAL <T> ($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:<this> type:T flags:
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-bar>() on T: T'
GET_VAR 'this@bar: T' type=T origin=null
FUN name:<set-bar> visibility:public modality:FINAL <T> ($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:<this> type:T flags:
VALUE_PARAMETER name:value index:0 type:T flags:
BLOCK_BODY
CALL '<set-recivier>(Any?): Unit' type=kotlin.Unit origin=EQ
<set-?>: GET_VAR 'this@bar: T' type=T origin=null
CALL '<set-value2>(Any?): Unit' type=kotlin.Unit origin=EQ
<set-?>: 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<kotlin.String?, kotlin.String?> visibility:public flags:final,static
EXPRESSION_BODY
PROPERTY_REFERENCE 'bar: T on T' field='bar: T on T' getter='<get-bar>() on T: T' setter='<set-bar>(T) on T: Unit' type=kotlin.reflect.KMutableProperty1<kotlin.String?, kotlin.String?> origin=null
<T>: kotlin.String?
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-barRef> visibility:public modality:FINAL <> () returnType:kotlin.reflect.KMutableProperty1<kotlin.String?, kotlin.String?> flags:
correspondingProperty: PROPERTY name:barRef visibility:public modality:FINAL flags:val
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-barRef>(): KMutableProperty1<String?, String?>'
GET_FIELD 'barRef: KMutableProperty1<String?, String?>' type=kotlin.reflect.KMutableProperty1<kotlin.String?, kotlin.String?> origin=null
@@ -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");