K1: Support referencing class context receivers in a form of this@Name

This commit is contained in:
Denis.Zharkov
2022-03-24 13:35:40 +03:00
committed by teamcity
parent c33f06b9e4
commit 4349060db1
10 changed files with 83 additions and 43 deletions
@@ -121,20 +121,7 @@ fun StatementGenerator.generateReceiver(defaultStartOffset: Int, defaultEndOffse
context.symbolTable.referenceValueParameter(receiverClassDescriptor.thisAsReceiverParameter)
)
}
is ContextClassReceiver -> {
val receiverClassDescriptor = receiver.classDescriptor
val thisAsReceiverParameter = receiverClassDescriptor.thisAsReceiverParameter
val thisReceiver = IrGetValueImpl(
defaultStartOffset, defaultEndOffset,
thisAsReceiverParameter.type.toIrType(),
context.symbolTable.referenceValue(thisAsReceiverParameter)
)
IrGetFieldImpl(
defaultStartOffset, defaultEndOffset,
context.additionalDescriptorStorage.getSyntheticField(receiver).symbol,
irReceiverType, thisReceiver
)
}
is ContextClassReceiver -> loadContextReceiver(receiver, defaultStartOffset, defaultEndOffset)
is ThisClassReceiver ->
generateThisOrSuperReceiver(receiver, receiver.classDescriptor)
is SuperCallReceiverValue ->
@@ -161,6 +148,26 @@ fun StatementGenerator.generateReceiver(defaultStartOffset: Int, defaultEndOffse
}
}
fun StatementGenerator.loadContextReceiver(
receiver: ContextClassReceiver,
defaultStartOffset: Int, defaultEndOffset: Int,
): IrGetFieldImpl {
val receiverClassDescriptor = receiver.classDescriptor
val thisAsReceiverParameter = receiverClassDescriptor.thisAsReceiverParameter
val thisReceiver = IrGetValueImpl(
defaultStartOffset, defaultEndOffset,
thisAsReceiverParameter.type.toIrType(),
context.symbolTable.referenceValue(thisAsReceiverParameter)
)
return IrGetFieldImpl(
defaultStartOffset, defaultEndOffset,
context.additionalDescriptorStorage.getSyntheticField(receiver).symbol,
receiver.type.toIrType(), thisReceiver
)
}
fun StatementGenerator.generateSingletonReference(
descriptor: ClassDescriptor,
startOffset: Int,
@@ -17,10 +17,7 @@
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.backend.common.BackendException
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.Scope
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
@@ -46,6 +43,7 @@ import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.scopes.receivers.ContextClassReceiver
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -415,23 +413,26 @@ class StatementGenerator(
override fun visitThisExpression(expression: KtThisExpression, data: Nothing?): IrExpression {
val referenceTarget = getOrFail(BindingContext.REFERENCE_TARGET, expression.instanceReference) { "No reference target for this" }
val receiverParameter =
getOrFail<KtReferenceExpression, ReceiverParameterDescriptor>(
BindingContext.THIS_REFERENCE_TARGET, expression.instanceReference
) { "No reference target for this" }
val startOffset = expression.startOffsetSkippingComments
val endOffset = expression.endOffset
return when (referenceTarget) {
is ClassDescriptor ->
generateThisReceiver(startOffset, endOffset, referenceTarget.thisAsReceiverParameter.type, referenceTarget)
when (receiverParameter.value) {
is ContextClassReceiver -> loadContextReceiver(receiverParameter.value as ContextClassReceiver, startOffset, endOffset)
else -> generateThisReceiver(
startOffset, endOffset, referenceTarget.thisAsReceiverParameter.type, referenceTarget
)
}
is CallableDescriptor -> {
val resolvedCall = getResolvedCall(expression)
val receivers = listOfNotNull(referenceTarget.extensionReceiverParameter) + referenceTarget.contextReceiverParameters
val receiver = receivers.find {
it == resolvedCall?.candidateDescriptor
} ?: referenceTarget.extensionReceiverParameter ?: error("No receiver: $referenceTarget")
val receiverType = receiver.type.toIrType()
val receiverType = receiverParameter.type.toIrType()
IrGetValueImpl(
startOffset, endOffset,
receiverType,
context.symbolTable.referenceValueParameter(receiver)
context.symbolTable.referenceValueParameter(receiverParameter)
)
}
@@ -513,4 +514,4 @@ abstract class StatementGeneratorExtension(val statementGenerator: StatementGene
fun KtExpression.genStmt() = statementGenerator.generateStatement(this)
fun KotlinType.toIrType() = with(statementGenerator) { toIrType() }
fun translateType(kotlinType: KotlinType) = kotlinType.toIrType()
}
}