Adjust receivers for possibly synthetic properties access

Synthetic property accessors are treated as extension functions on Java
classes by the front-end. However, underlying Java accessor methods are
proper members.
This commit is contained in:
Dmitry Petrov
2018-07-19 15:37:57 +03:00
parent 73acc86785
commit 779cae7db5
7 changed files with 67 additions and 18 deletions
@@ -140,18 +140,17 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
endOffset: Int,
call: CallBuilder
): IrExpression {
return call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) }
val getMethodDescriptor = descriptor.unwrappedGetMethod
val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) }
val getterDescriptor = descriptor.unwrappedGetMethod
if (getterDescriptor != null) {
val getterSymbol = context.symbolTable.referenceFunction(getterDescriptor.original)
return if (getMethodDescriptor != null) {
call.callReceiver.adjustForCallee(getMethodDescriptor).call { dispatchReceiverValue, extensionReceiverValue ->
val getterSymbol = context.symbolTable.referenceFunction(getMethodDescriptor.original)
IrGetterCallImpl(
startOffset, endOffset,
descriptor.type.toIrType(),
getterSymbol,
getterDescriptor,
getMethodDescriptor,
descriptor.typeParametersCount,
dispatchReceiverValue?.load(),
extensionReceiverValue?.load(),
@@ -160,8 +159,9 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
).apply {
putTypeArguments(call.typeArguments) { it.toIrType() }
}
} else {
}
} else {
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
val fieldSymbol = context.symbolTable.referenceField(descriptor.original)
IrGetFieldImpl(
startOffset, endOffset,
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
@@ -23,3 +24,27 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
fun IrVariable.defaultLoad(): IrExpression =
IrGetValueImpl(startOffset, endOffset, type, symbol)
fun CallReceiver.adjustForCallee(callee: CallableMemberDescriptor): CallReceiver =
object : CallReceiver {
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression =
this@adjustForCallee.call { dispatchReceiverValue, extensionReceiverValue ->
val numReceiversPresent = listOfNotNull(dispatchReceiverValue, extensionReceiverValue).size
val numReceiversExpected = listOfNotNull(callee.dispatchReceiverParameter, callee.extensionReceiverParameter).size
if (numReceiversPresent != numReceiversExpected)
throw AssertionError("Mismatching receivers for $callee: $numReceiversPresent, expected: $numReceiversExpected")
val newDispatchReceiverValue =
when {
callee.dispatchReceiverParameter == null -> null
dispatchReceiverValue != null -> dispatchReceiverValue
else -> extensionReceiverValue
}
val newExtensionReceiverValue =
when {
callee.extensionReceiverParameter == null -> null
dispatchReceiverValue != null && callee.dispatchReceiverParameter == null -> dispatchReceiverValue
else -> extensionReceiverValue
}
withDispatchAndExtensionReceivers(newDispatchReceiverValue, newExtensionReceiverValue)
}
}
@@ -141,11 +141,11 @@ class AccessorPropertyLValue(
}
override fun load(): IrExpression =
callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
callReceiver.adjustForCallee(getterDescriptor!!).call { dispatchReceiverValue, extensionReceiverValue ->
IrGetterCallImpl(
startOffset, endOffset,
type,
getter!!, getterDescriptor!!,
getter!!, getterDescriptor,
typeArgumentsCount,
dispatchReceiverValue?.load(),
extensionReceiverValue?.load(),
@@ -157,11 +157,11 @@ class AccessorPropertyLValue(
}
override fun store(irExpression: IrExpression) =
callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
callReceiver.adjustForCallee(setterDescriptor!!).call { dispatchReceiverValue, extensionReceiverValue ->
IrSetterCallImpl(
startOffset, endOffset,
context.irBuiltIns.unitType,
setter!!, setterDescriptor!!,
setter!!, setterDescriptor,
typeArgumentsCount,
dispatchReceiverValue?.load(),
extensionReceiverValue?.load(),