diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt index ac753c34bce..a67371276f7 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt @@ -140,7 +140,7 @@ fun StatementGenerator.generateReceiver(defaultStartOffset: Int, defaultEndOffse is SuperCallReceiverValue -> generateThisOrSuperReceiver(receiver, receiver.thisType.constructor.declarationDescriptor as ClassDescriptor) is ExpressionReceiver -> - generateExpression(receiver.expression) + generateStatement(receiver.expression) as IrExpression is ExtensionReceiver -> { IrGetValueImpl( defaultStartOffset, defaultStartOffset, irReceiverType, diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt index 76be1cbd365..0774e0df74b 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt @@ -306,7 +306,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator } } - private fun generateFunctionCall( + internal fun generateFunctionCall( functionDescriptor: FunctionDescriptor, startOffset: Int, endOffset: Int, diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt index e8405730a57..b99c953f303 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt @@ -25,7 +25,9 @@ import org.jetbrains.kotlin.ir.descriptors.IrBuiltInsOverDescriptors import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol -import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classifierOrFail +import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.impl.originalKotlinType import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name @@ -527,15 +529,19 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat } } - private fun generateBinaryOperatorAsCall(expression: KtBinaryExpression, origin: IrStatementOrigin?): IrExpression = - if (isDynamicBinaryOperator(expression)) - generateDynamicBinaryExpression(expression) - else - CallGenerator(statementGenerator) - .generateCall( - expression.startOffsetSkippingComments, expression.endOffset, - statementGenerator.pregenerateCall(getResolvedCall(expression)!!), origin - ) + private fun generateBinaryOperatorAsCall(expression: KtBinaryExpression, origin: IrStatementOrigin?): IrExpression { + if (isDynamicBinaryOperator(expression)) { + return generateDynamicBinaryExpression(expression) + } + val callBuilder = statementGenerator.pregenerateCall(getResolvedCall(expression)!!) + return CallGenerator(statementGenerator).generateFunctionCall( + callBuilder.descriptor as? FunctionDescriptor + ?: throw AssertionError("Operator call resolved to a non-function: ${callBuilder.descriptor}"), + expression.startOffsetSkippingComments, expression.endOffset, + origin, + callBuilder + ) + } private fun generatePrefixOperatorAsCall(expression: KtPrefixExpression, origin: IrStatementOrigin): IrExpression { val resolvedCall = getResolvedCall(expression)!! diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/CallBuilder.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/CallBuilder.kt index 4689604e3f2..16a5b947041 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/CallBuilder.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/CallBuilder.kt @@ -84,11 +84,11 @@ val CallBuilder.explicitReceiverType: KotlinType? fun CallBuilder.setExplicitReceiverValue(explicitReceiverValue: IntermediateValue) { val previousCallReceiver = callReceiver callReceiver = object : CallReceiver { - override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List) -> IrExpression): IrExpression { + override fun call(builder: CallExpressionBuilder): IrExpression { return previousCallReceiver.call { dispatchReceiverValue, _, contextReceiverValues -> val newDispatchReceiverValue = if (hasExtensionReceiver) dispatchReceiverValue else explicitReceiverValue val newExtensionReceiverValue = if (hasExtensionReceiver) explicitReceiverValue else null - withDispatchAndExtensionAndContextReceivers(newDispatchReceiverValue, newExtensionReceiverValue, contextReceiverValues) + builder.withReceivers(newDispatchReceiverValue, newExtensionReceiverValue, contextReceiverValues) } } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/ExtensionInvokeCallReceiver.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/ExtensionInvokeCallReceiver.kt index bd05ec35911..78cc95ac9bd 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/ExtensionInvokeCallReceiver.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/ExtensionInvokeCallReceiver.kt @@ -23,8 +23,7 @@ class ExtensionInvokeCallReceiver( private val functionReceiver: IntermediateValue, private val extensionInvokeReceiver: IntermediateValue ) : CallReceiver { - - override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List) -> IrExpression): IrExpression { + override fun call(builder: CallExpressionBuilder): IrExpression { // extensionInvokeReceiver is actually a first argument: // receiver.extFun(p1, ..., pN) // => @@ -34,6 +33,6 @@ class ExtensionInvokeCallReceiver( "Extension 'invoke' call should have null as its 1st value argument, got: ${callBuilder.irValueArgumentsByIndex[0]}" } callBuilder.irValueArgumentsByIndex[0] = extensionInvokeReceiver.load() - return withDispatchAndExtensionAndContextReceivers(functionReceiver, null, emptyList()) + return builder.withReceivers(functionReceiver, null, emptyList()) } } \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/IrUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/IrUtils.kt index 2233fa0a689..7dac82195f1 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/IrUtils.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/IrUtils.kt @@ -27,7 +27,7 @@ fun IrVariable.loadAt(startOffset: Int, endOffset: Int): IrExpression = fun CallReceiver.adjustForCallee(callee: CallableMemberDescriptor): CallReceiver = object : CallReceiver { - override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List) -> IrExpression): IrExpression = + override fun call(builder: CallExpressionBuilder): IrExpression = this@adjustForCallee.call { dispatchReceiverValue, extensionReceiverValue, contextReceiverValues -> val numReceiversPresent = listOfNotNull(dispatchReceiverValue, extensionReceiverValue).size val numReceiversExpected = listOfNotNull(callee.dispatchReceiverParameter, callee.extensionReceiverParameter).size @@ -46,7 +46,7 @@ fun CallReceiver.adjustForCallee(callee: CallableMemberDescriptor): CallReceiver dispatchReceiverValue != null && callee.dispatchReceiverParameter == null -> dispatchReceiverValue else -> extensionReceiverValue } - withDispatchAndExtensionAndContextReceivers(newDispatchReceiverValue, newExtensionReceiverValue, contextReceiverValues) + builder.withReceivers(newDispatchReceiverValue, newExtensionReceiverValue, contextReceiverValues) } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SafeCallReceiver.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SafeCallReceiver.kt index 792a5ab870e..aa4ac83b91a 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SafeCallReceiver.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SafeCallReceiver.kt @@ -35,8 +35,7 @@ class SafeCallReceiver( val dispatchReceiver: IntermediateValue?, val isStatement: Boolean ) : CallReceiver { - - override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List) -> IrExpression): IrExpression { + override fun call(builder: CallExpressionBuilder): IrExpression { val irTmp = generator.scope.createTemporaryVariable(extensionReceiver?.load() ?: dispatchReceiver!!.load(), "safe_receiver") val safeReceiverValue = VariableLValue(generator.context, irTmp) @@ -50,7 +49,7 @@ class SafeCallReceiver( extensionReceiverValue = null } - val irResult = withDispatchAndExtensionAndContextReceivers(dispatchReceiverValue, extensionReceiverValue, contextReceivers) + val irResult = builder.withReceivers(dispatchReceiverValue, extensionReceiverValue, contextReceivers) val resultType = if (isStatement) generator.context.irBuiltIns.unitType else irResult.type.makeNullable() diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SafeExtensionInvokeCallReceiver.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SafeExtensionInvokeCallReceiver.kt index 23ef3f17c1a..15aa028455f 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SafeExtensionInvokeCallReceiver.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SafeExtensionInvokeCallReceiver.kt @@ -32,8 +32,7 @@ class SafeExtensionInvokeCallReceiver( val functionReceiver: IntermediateValue, val extensionInvokeReceiver: IntermediateValue ) : CallReceiver { - - override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List) -> IrExpression): IrExpression { + override fun call(builder: CallExpressionBuilder): IrExpression { // extensionInvokeReceiver is actually a first argument: // receiver?.extFun(p1, ..., pN) // => @@ -49,7 +48,7 @@ class SafeExtensionInvokeCallReceiver( "Safe extension 'invoke' call should have null as its 1st value argument, got: ${callBuilder.irValueArgumentsByIndex[0]}" } callBuilder.irValueArgumentsByIndex[0] = safeReceiverValue.load() - val irResult = withDispatchAndExtensionAndContextReceivers(functionReceiver, null, emptyList()) + val irResult = builder.withReceivers(functionReceiver, null, emptyList()) val resultType = irResult.type.makeNullable() diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SimpleCallReceiver.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SimpleCallReceiver.kt index 43e44753f72..6ad30c0e71b 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SimpleCallReceiver.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SimpleCallReceiver.kt @@ -23,8 +23,7 @@ class SimpleCallReceiver( private val extensionReceiverValue: IntermediateValue?, private val contextReceiverValues: List ) : CallReceiver { - - override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List) -> IrExpression): IrExpression { - return withDispatchAndExtensionAndContextReceivers(dispatchReceiverValue, extensionReceiverValue, contextReceiverValues) + override fun call(builder: CallExpressionBuilder): IrExpression { + return builder.withReceivers(dispatchReceiverValue, extensionReceiverValue, contextReceiverValues) } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/Values.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/Values.kt index 178c462f2a9..99eae96d3cc 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/Values.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/Values.kt @@ -18,7 +18,6 @@ package org.jetbrains.kotlin.psi2ir.intermediate import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.types.IrType -import org.jetbrains.kotlin.types.KotlinType interface IntermediateValue { fun load(): IrExpression @@ -35,6 +34,14 @@ interface AssignmentReceiver { fun assign(value: IrExpression): IrExpression = assign { it.store(value) } } -interface CallReceiver { - fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List) -> IrExpression): IrExpression +fun interface CallExpressionBuilder { + fun withReceivers( + dispatchReceiver: IntermediateValue?, + extensionReceiver: IntermediateValue?, + contextReceivers: List + ): IrExpression +} + +interface CallReceiver { + fun call(builder: CallExpressionBuilder): IrExpression }