[PSI2IR] Generate IR for functions and calls with context receivers
This commit is contained in:
committed by
TeamCityServer
parent
f4ddf66ac4
commit
307f318c9e
+28
@@ -16107,6 +16107,34 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
public void testWhenFail() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/extensionFunctions/contextReceivers")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class ContextReceivers {
|
||||
@Test
|
||||
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("dp.kt")
|
||||
public void testDp() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/dp.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("plusMatrix.kt")
|
||||
public void testPlusMatrix() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/plusMatrix.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simpleCall.kt")
|
||||
public void testSimpleCall() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/simpleCall.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+22
-6
@@ -66,8 +66,13 @@ fun StatementGenerator.generateReceiver(ktDefaultElement: KtElement, receiver: R
|
||||
fun StatementGenerator.generateReceiver(defaultStartOffset: Int, defaultEndOffset: Int, receiver: ReceiverValue): IntermediateValue {
|
||||
val irReceiverType =
|
||||
when (receiver) {
|
||||
is ExtensionReceiver ->
|
||||
receiver.declarationDescriptor.extensionReceiverParameter!!.type.toIrType()
|
||||
is ExtensionReceiver -> {
|
||||
val receiverParameters =
|
||||
receiver.declarationDescriptor.contextReceiverParameters + listOfNotNull(receiver.declarationDescriptor.extensionReceiverParameter)
|
||||
val receiverParameter = receiverParameters.firstOrNull { it.value == receiver }
|
||||
?: receiver.declarationDescriptor.extensionReceiverParameter!!
|
||||
receiverParameter.type.toIrType()
|
||||
}
|
||||
else ->
|
||||
receiver.type.toIrType()
|
||||
}
|
||||
@@ -93,11 +98,16 @@ fun StatementGenerator.generateReceiver(defaultStartOffset: Int, defaultEndOffse
|
||||
generateThisOrSuperReceiver(receiver, receiver.thisType.constructor.declarationDescriptor as ClassDescriptor)
|
||||
is ExpressionReceiver ->
|
||||
generateExpression(receiver.expression)
|
||||
is ExtensionReceiver ->
|
||||
is ExtensionReceiver -> {
|
||||
val receiverParameters = listOfNotNull(receiver.declarationDescriptor.extensionReceiverParameter) +
|
||||
receiver.declarationDescriptor.contextReceiverParameters
|
||||
val receiverParameter = receiverParameters.singleOrNull { it.value == receiver }
|
||||
?: receiver.declarationDescriptor.extensionReceiverParameter!!
|
||||
IrGetValueImpl(
|
||||
defaultStartOffset, defaultStartOffset, irReceiverType,
|
||||
context.symbolTable.referenceValueParameter(receiver.declarationDescriptor.extensionReceiverParameter!!)
|
||||
context.symbolTable.referenceValueParameter(receiverParameter)
|
||||
)
|
||||
}
|
||||
else ->
|
||||
throw AssertionError("Unexpected receiver: ${receiver::class.java.simpleName}")
|
||||
}
|
||||
@@ -170,11 +180,13 @@ fun StatementGenerator.generateCallReceiver(
|
||||
calleeDescriptor: CallableDescriptor,
|
||||
dispatchReceiver: ReceiverValue?,
|
||||
extensionReceiver: ReceiverValue?,
|
||||
contextReceivers: List<ReceiverValue>,
|
||||
isSafe: Boolean,
|
||||
isAssignmentReceiver: Boolean = false
|
||||
): CallReceiver {
|
||||
val dispatchReceiverValue: IntermediateValue?
|
||||
val extensionReceiverValue: IntermediateValue?
|
||||
val contextReceiverValues: List<IntermediateValue>
|
||||
val startOffset = ktDefaultElement.startOffsetSkippingComments
|
||||
val endOffset = ktDefaultElement.endOffset
|
||||
when (calleeDescriptor) {
|
||||
@@ -184,6 +196,7 @@ fun StatementGenerator.generateCallReceiver(
|
||||
}
|
||||
dispatchReceiverValue = generateReceiverForCalleeImportedFromObject(startOffset, endOffset, calleeDescriptor)
|
||||
extensionReceiverValue = generateReceiverOrNull(ktDefaultElement, extensionReceiver)
|
||||
contextReceiverValues = contextReceivers.mapNotNull { generateReceiverOrNull(ktDefaultElement, it) }
|
||||
}
|
||||
is TypeAliasConstructorDescriptor -> {
|
||||
assert(!(dispatchReceiver != null && extensionReceiver != null)) {
|
||||
@@ -192,20 +205,22 @@ fun StatementGenerator.generateCallReceiver(
|
||||
}
|
||||
dispatchReceiverValue = generateReceiverOrNull(ktDefaultElement, extensionReceiver ?: dispatchReceiver)
|
||||
extensionReceiverValue = null
|
||||
contextReceiverValues = emptyList()
|
||||
}
|
||||
else -> {
|
||||
dispatchReceiverValue = generateReceiverOrNull(ktDefaultElement, dispatchReceiver)
|
||||
extensionReceiverValue = generateReceiverOrNull(ktDefaultElement, extensionReceiver)
|
||||
contextReceiverValues = contextReceivers.mapNotNull { generateReceiverOrNull(ktDefaultElement, it) }
|
||||
}
|
||||
}
|
||||
|
||||
return when {
|
||||
!isSafe ->
|
||||
SimpleCallReceiver(dispatchReceiverValue, extensionReceiverValue)
|
||||
SimpleCallReceiver(dispatchReceiverValue, extensionReceiverValue, contextReceiverValues)
|
||||
extensionReceiverValue != null || dispatchReceiverValue != null ->
|
||||
SafeCallReceiver(
|
||||
this, startOffset, endOffset,
|
||||
extensionReceiverValue, dispatchReceiverValue, isAssignmentReceiver
|
||||
extensionReceiverValue, contextReceiverValues, dispatchReceiverValue, isAssignmentReceiver
|
||||
)
|
||||
else ->
|
||||
throw AssertionError("Safe call should have an explicit receiver: ${ktDefaultElement.text}")
|
||||
@@ -697,6 +712,7 @@ fun StatementGenerator.pregenerateCallReceivers(resolvedCall: ResolvedCall<*>):
|
||||
resolvedCall.resultingDescriptor,
|
||||
resolvedCall.dispatchReceiver,
|
||||
resolvedCall.extensionReceiver,
|
||||
resolvedCall.contextReceivers,
|
||||
isSafe = resolvedCall.call.isSafeCall()
|
||||
)
|
||||
|
||||
|
||||
+6
-2
@@ -273,7 +273,9 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
|
||||
descriptor.type.toIrType(),
|
||||
descriptor.name.asString(),
|
||||
statementGenerator.generateCallReceiver(
|
||||
ktLeft, descriptor, resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver,
|
||||
ktLeft, descriptor, resolvedCall.dispatchReceiver,
|
||||
resolvedCall.extensionReceiver,
|
||||
resolvedCall.contextReceivers,
|
||||
isSafe = resolvedCall.call.isSafeCall(),
|
||||
isAssignmentReceiver = isAssignmentStatement
|
||||
)
|
||||
@@ -285,7 +287,9 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
|
||||
}
|
||||
else -> {
|
||||
val propertyReceiver = statementGenerator.generateCallReceiver(
|
||||
ktLeft, descriptor, resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver,
|
||||
ktLeft, descriptor, resolvedCall.dispatchReceiver,
|
||||
resolvedCall.extensionReceiver,
|
||||
resolvedCall.contextReceivers,
|
||||
isSafe = resolvedCall.call.isSafeCall(),
|
||||
isAssignmentReceiver = isAssignmentStatement
|
||||
)
|
||||
|
||||
@@ -55,7 +55,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
is FunctionDescriptor ->
|
||||
generateFunctionCall(descriptor, startOffset, endOffset, origin, call)
|
||||
else ->
|
||||
call.callReceiver.call { _, _ ->
|
||||
call.callReceiver.call { _, _, _ ->
|
||||
generateValueReference(startOffset, endOffset, descriptor, call.original, origin)
|
||||
}
|
||||
}
|
||||
@@ -155,7 +155,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
}
|
||||
|
||||
fun generateDelegatingConstructorCall(startOffset: Int, endOffset: Int, call: CallBuilder): IrExpression =
|
||||
call.callReceiver.call { dispatchReceiver, extensionReceiver ->
|
||||
call.callReceiver.call { dispatchReceiver, extensionReceiver, contextReceivers ->
|
||||
val descriptor = call.descriptor as? ClassConstructorDescriptor
|
||||
?: throw AssertionError("Class constructor expected: ${call.descriptor}")
|
||||
val constructorSymbol = context.symbolTable.referenceConstructor(descriptor.original)
|
||||
@@ -169,7 +169,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
this.dispatchReceiver = dispatchReceiver?.load()
|
||||
this.extensionReceiver = extensionReceiver?.load()
|
||||
}
|
||||
addParametersToCall(startOffset, endOffset, call, irCall, context.irBuiltIns.unitType)
|
||||
addParametersToCall(startOffset, endOffset, call, irCall, context.irBuiltIns.unitType, contextReceivers.map { it.load() })
|
||||
}
|
||||
|
||||
fun generateEnumConstructorSuperCall(startOffset: Int, endOffset: Int, call: CallBuilder): IrExpression {
|
||||
@@ -178,9 +178,10 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
val classDescriptor = constructorDescriptor.containingDeclaration
|
||||
if (classDescriptor.kind != ClassKind.ENUM_CLASS) throw AssertionError("Enum class constructor expected: $classDescriptor")
|
||||
|
||||
return call.callReceiver.call { dispatchReceiver, extensionReceiver ->
|
||||
return call.callReceiver.call { dispatchReceiver, extensionReceiver, contextReceivers ->
|
||||
if (dispatchReceiver != null) throw AssertionError("Dispatch receiver should be null: $dispatchReceiver")
|
||||
if (extensionReceiver != null) throw AssertionError("Extension receiver should be null: $extensionReceiver")
|
||||
if (contextReceivers.isNotEmpty()) throw AssertionError("Context receivers should be empty: $contextReceivers")
|
||||
val descriptor = constructorDescriptor.original
|
||||
val constructorSymbol = context.symbolTable.referenceConstructor(descriptor)
|
||||
val returnType = constructorDescriptor.returnType.toIrType()
|
||||
@@ -188,7 +189,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
startOffset, endOffset, returnType, constructorSymbol, descriptor.typeParametersCount, descriptor.valueParameters.size
|
||||
)
|
||||
context.callToSubstitutedDescriptorMap[irCall] = constructorDescriptor
|
||||
addParametersToCall(startOffset, endOffset, call, irCall, irCall.type)
|
||||
addParametersToCall(startOffset, endOffset, call, irCall, irCall.type, emptyList())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,7 +209,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
}
|
||||
val fieldSymbol =
|
||||
context.symbolTable.referenceField(context.extensions.remapDebuggerFieldPropertyDescriptor(descriptor.resolveFakeOverride().original))
|
||||
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||
IrGetFieldImpl(
|
||||
startOffset, endOffset,
|
||||
fieldSymbol,
|
||||
@@ -220,36 +221,40 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
}
|
||||
} else {
|
||||
val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) }
|
||||
call.callReceiver.adjustForCallee(getMethodDescriptor).call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
if (descriptor.isDynamic()) {
|
||||
val dispatchReceiver = getDynamicExpressionReceiver(dispatchReceiverValue, extensionReceiverValue, descriptor)
|
||||
call.callReceiver.adjustForCallee(getMethodDescriptor)
|
||||
.call { dispatchReceiverValue, extensionReceiverValue, contextReceiverValues ->
|
||||
if (descriptor.isDynamic()) {
|
||||
val dispatchReceiver = getDynamicExpressionReceiver(dispatchReceiverValue, extensionReceiverValue, descriptor)
|
||||
|
||||
IrDynamicMemberExpressionImpl(
|
||||
startOffset, endOffset,
|
||||
irType,
|
||||
descriptor.name.asString(),
|
||||
dispatchReceiver
|
||||
)
|
||||
} else {
|
||||
val getterSymbol = context.symbolTable.referenceSimpleFunction(getMethodDescriptor.original)
|
||||
IrCallImpl(
|
||||
startOffset, endOffset,
|
||||
irType,
|
||||
getterSymbol,
|
||||
descriptor.typeParametersCount,
|
||||
0,
|
||||
IrStatementOrigin.GET_PROPERTY,
|
||||
superQualifierSymbol
|
||||
).apply {
|
||||
context.callToSubstitutedDescriptorMap[this] = computeSubstitutedSyntheticAccessor(
|
||||
descriptor, getMethodDescriptor, descriptor.getter!!
|
||||
IrDynamicMemberExpressionImpl(
|
||||
startOffset, endOffset,
|
||||
irType,
|
||||
descriptor.name.asString(),
|
||||
dispatchReceiver
|
||||
)
|
||||
putTypeArguments(call.typeArguments) { it.toIrType() }
|
||||
dispatchReceiver = dispatchReceiverValue?.load()
|
||||
extensionReceiver = extensionReceiverValue?.load()
|
||||
} else {
|
||||
val getterSymbol = context.symbolTable.referenceSimpleFunction(getMethodDescriptor.original)
|
||||
IrCallImpl(
|
||||
startOffset, endOffset,
|
||||
irType,
|
||||
getterSymbol,
|
||||
descriptor.typeParametersCount,
|
||||
descriptor.contextReceiverParameters.size,
|
||||
IrStatementOrigin.GET_PROPERTY,
|
||||
superQualifierSymbol
|
||||
).apply {
|
||||
context.callToSubstitutedDescriptorMap[this] = computeSubstitutedSyntheticAccessor(
|
||||
descriptor, getMethodDescriptor, descriptor.getter!!
|
||||
)
|
||||
|
||||
putTypeArguments(call.typeArguments) { it.toIrType() }
|
||||
dispatchReceiver = dispatchReceiverValue?.load()
|
||||
extensionReceiver = extensionReceiverValue?.load()
|
||||
val contextReceivers = contextReceiverValues.map { it.load() }
|
||||
addParametersToCall(startOffset, endOffset, call, this, irType, contextReceivers)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,7 +285,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
origin: IrStatementOrigin?,
|
||||
call: CallBuilder
|
||||
): IrExpression =
|
||||
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue, contextReceiverValues ->
|
||||
val irType = constructorDescriptor.returnType.toIrType()
|
||||
val originalSymbol = context.symbolTable.referenceConstructor(constructorDescriptor.original)
|
||||
|
||||
@@ -294,7 +299,8 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
putTypeArguments(call.typeArguments) { it.toIrType() }
|
||||
dispatchReceiver = dispatchReceiverValue?.load()
|
||||
extensionReceiver = extensionReceiverValue?.load()
|
||||
addParametersToCall(startOffset, endOffset, call, this, irType)
|
||||
val contextReceivers = contextReceiverValues.map { it.load() }
|
||||
addParametersToCall(startOffset, endOffset, call, this, irType, contextReceivers)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,7 +311,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
origin: IrStatementOrigin?,
|
||||
call: CallBuilder
|
||||
): IrExpression =
|
||||
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue, contextReceiverValues ->
|
||||
val irType = functionDescriptor.returnType!!.toIrType()
|
||||
|
||||
if (functionDescriptor.isDynamic()) {
|
||||
@@ -369,7 +375,8 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
putTypeArguments(call.typeArguments) { it.toIrType() }
|
||||
dispatchReceiver = dispatchReceiverValue?.load()
|
||||
extensionReceiver = extensionReceiverValue?.load()
|
||||
addParametersToCall(startOffset, endOffset, call, this, irType)
|
||||
val contextReceivers = contextReceiverValues.map { it.load() }
|
||||
addParametersToCall(startOffset, endOffset, call, this, irType, contextReceivers)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -379,14 +386,18 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
endOffset: Int,
|
||||
call: CallBuilder,
|
||||
irCall: IrFunctionAccessExpression,
|
||||
irResultType: IrType
|
||||
irResultType: IrType,
|
||||
contextReceivers: List<IrExpression>
|
||||
): IrExpression =
|
||||
if (call.isValueArgumentReorderingRequired()) {
|
||||
generateCallWithArgumentReordering(irCall, startOffset, endOffset, call, irResultType)
|
||||
} else {
|
||||
for ((index, valueArgument) in contextReceivers.withIndex()) {
|
||||
irCall.putValueArgument(index, valueArgument)
|
||||
}
|
||||
val valueArguments = call.getValueArgumentsInParameterOrder()
|
||||
for ((index, valueArgument) in valueArguments.withIndex()) {
|
||||
irCall.putValueArgument(index, valueArgument)
|
||||
irCall.putValueArgument(index + contextReceivers.size, valueArgument)
|
||||
}
|
||||
irCall
|
||||
}
|
||||
|
||||
+2
-2
@@ -103,7 +103,7 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
|
||||
IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR,
|
||||
accessorDescriptor
|
||||
).buildWithScope { irAccessor ->
|
||||
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irAccessor, ktProperty, null)
|
||||
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irAccessor, ktProperty, null, emptyList())
|
||||
irAccessor.body = generateBody(irAccessor)
|
||||
}
|
||||
|
||||
@@ -363,7 +363,7 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
|
||||
IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR,
|
||||
getterDescriptor
|
||||
).buildWithScope { irAccessor ->
|
||||
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irAccessor, ktDelegate, null)
|
||||
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irAccessor, ktDelegate, null, emptyList())
|
||||
irAccessor.body = generateBody(irAccessor)
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -44,7 +44,7 @@ class EnumClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De
|
||||
IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER,
|
||||
valuesFunction
|
||||
).also { irFunction ->
|
||||
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irFunction, null, null)
|
||||
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irFunction, null, null, emptyList())
|
||||
irFunction.body = IrSyntheticBodyImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrSyntheticBodyKind.ENUM_VALUES)
|
||||
}
|
||||
)
|
||||
@@ -63,7 +63,7 @@ class EnumClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De
|
||||
IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER,
|
||||
valueOfFunction
|
||||
).also { irFunction ->
|
||||
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irFunction, null, null)
|
||||
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irFunction, null, null, emptyList())
|
||||
irFunction.body = IrSyntheticBodyImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrSyntheticBodyKind.ENUM_VALUEOF)
|
||||
}
|
||||
)
|
||||
|
||||
+28
-12
@@ -50,6 +50,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
||||
declareSimpleFunction(
|
||||
ktFunction,
|
||||
ktFunction.receiverTypeReference,
|
||||
ktFunction.contextReceiverTypeReferences,
|
||||
origin,
|
||||
getOrFail(BindingContext.FUNCTION, ktFunction)
|
||||
) {
|
||||
@@ -60,6 +61,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
||||
declareSimpleFunction(
|
||||
ktFunction,
|
||||
null,
|
||||
emptyList(),
|
||||
IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA,
|
||||
getOrFail(BindingContext.FUNCTION, ktFunction)
|
||||
) {
|
||||
@@ -71,19 +73,20 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
||||
?.let {
|
||||
declareSimpleFunctionInner(it, ktElement, IrDeclarationOrigin.FAKE_OVERRIDE)
|
||||
.buildWithScope { irFunction ->
|
||||
generateFunctionParameterDeclarationsAndReturnType(irFunction, ktElement, null)
|
||||
generateFunctionParameterDeclarationsAndReturnType(irFunction, ktElement, null, emptyList())
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun declareSimpleFunction(
|
||||
ktFunction: KtFunction,
|
||||
ktReceiver: KtElement?,
|
||||
ktContextReceivers: List<KtElement>,
|
||||
origin: IrDeclarationOrigin,
|
||||
descriptor: FunctionDescriptor,
|
||||
generateBody: BodyGenerator.() -> IrBody?
|
||||
): IrSimpleFunction =
|
||||
declareSimpleFunctionInner(descriptor, ktFunction, origin).buildWithScope { irFunction ->
|
||||
generateFunctionParameterDeclarationsAndReturnType(irFunction, ktFunction, ktReceiver)
|
||||
generateFunctionParameterDeclarationsAndReturnType(irFunction, ktFunction, ktReceiver, ktContextReceivers)
|
||||
irFunction.body = createBodyGenerator(irFunction.symbol).generateBody()
|
||||
}
|
||||
|
||||
@@ -102,11 +105,12 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
||||
fun generateFunctionParameterDeclarationsAndReturnType(
|
||||
irFunction: IrFunction,
|
||||
ktParameterOwner: KtPureElement?,
|
||||
ktReceiverParameterElement: KtElement?
|
||||
ktReceiverParameterElement: KtElement?,
|
||||
ktContextReceiverParametersElements: List<KtElement>
|
||||
) {
|
||||
declarationGenerator.generateScopedTypeParameterDeclarations(irFunction, irFunction.descriptor.propertyIfAccessor.typeParameters)
|
||||
irFunction.returnType = irFunction.descriptor.returnType!!.toIrType()
|
||||
generateValueParameterDeclarations(irFunction, ktParameterOwner, ktReceiverParameterElement)
|
||||
generateValueParameterDeclarations(irFunction, ktParameterOwner, ktReceiverParameterElement, ktContextReceiverParametersElements)
|
||||
}
|
||||
|
||||
fun generatePropertyAccessor(
|
||||
@@ -121,7 +125,10 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
||||
).buildWithScope { irAccessor ->
|
||||
declarationGenerator.generateScopedTypeParameterDeclarations(irAccessor, descriptor.correspondingProperty.typeParameters)
|
||||
irAccessor.returnType = irAccessor.descriptor.returnType!!.toIrType()
|
||||
generateValueParameterDeclarations(irAccessor, ktAccessor ?: ktProperty, ktProperty.receiverTypeReference)
|
||||
generateValueParameterDeclarations(
|
||||
irAccessor, ktAccessor ?: ktProperty, ktProperty.receiverTypeReference,
|
||||
ktProperty.contextReceiverTypeReferences
|
||||
)
|
||||
val ktBodyExpression = ktAccessor?.bodyExpression
|
||||
irAccessor.body =
|
||||
if (ktBodyExpression != null)
|
||||
@@ -272,7 +279,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
||||
metadata = DescriptorMetadataSource.Function(it.descriptor)
|
||||
}
|
||||
}.buildWithScope { irConstructor ->
|
||||
generateValueParameterDeclarations(irConstructor, ktParametersElement, null)
|
||||
generateValueParameterDeclarations(irConstructor, ktParametersElement, null, emptyList())
|
||||
irConstructor.body = createBodyGenerator(irConstructor.symbol).generateBody()
|
||||
irConstructor.returnType = constructorDescriptor.returnType.toIrType()
|
||||
}
|
||||
@@ -286,13 +293,14 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
||||
else
|
||||
descriptor.typeParameters
|
||||
declarationGenerator.generateScopedTypeParameterDeclarations(irFunction, typeParameters)
|
||||
generateValueParameterDeclarations(irFunction, null, null, withDefaultValues = false)
|
||||
generateValueParameterDeclarations(irFunction, null, null, emptyList(), withDefaultValues = false)
|
||||
}
|
||||
|
||||
private fun generateValueParameterDeclarations(
|
||||
irFunction: IrFunction,
|
||||
ktParameterOwner: KtPureElement?,
|
||||
ktReceiverParameterElement: KtPureElement?,
|
||||
ktContextReceiverParameterElements: List<KtPureElement>,
|
||||
withDefaultValues: Boolean = true
|
||||
) {
|
||||
val functionDescriptor = irFunction.descriptor
|
||||
@@ -307,10 +315,16 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
||||
|
||||
val bodyGenerator = createBodyGenerator(irFunction.symbol)
|
||||
|
||||
val contextReceiversNumber = ktContextReceiverParameterElements.size
|
||||
assert(functionDescriptor.contextReceiverParameters.size == contextReceiversNumber)
|
||||
irFunction.valueParameters += functionDescriptor.contextReceiverParameters.mapIndexed { i, additionalReceiver ->
|
||||
declareParameter(additionalReceiver, ktContextReceiverParameterElements[i], irFunction, null, i)
|
||||
}
|
||||
|
||||
// Declare all the value parameters up first.
|
||||
irFunction.valueParameters += functionDescriptor.valueParameters.map { valueParameterDescriptor ->
|
||||
irFunction.valueParameters += functionDescriptor.valueParameters.mapIndexed { i, valueParameterDescriptor ->
|
||||
val ktParameter = DescriptorToSourceUtils.getSourceFromDescriptor(valueParameterDescriptor) as? KtParameter
|
||||
declareParameter(valueParameterDescriptor, ktParameter, irFunction)
|
||||
declareParameter(valueParameterDescriptor, ktParameter, irFunction, null, i + contextReceiversNumber)
|
||||
}
|
||||
// Only after value parameters have been declared, generate default values. This ensures
|
||||
// that forward references to other parameters works in default value lambdas. For example:
|
||||
@@ -318,7 +332,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
||||
// fun f(f1: () -> String = { f2() },
|
||||
// f2: () -> String) = f1()
|
||||
if (withDefaultValues) {
|
||||
irFunction.valueParameters.forEachIndexed { index, irValueParameter ->
|
||||
irFunction.valueParameters.drop(contextReceiversNumber).forEachIndexed { index, irValueParameter ->
|
||||
val valueParameterDescriptor = functionDescriptor.valueParameters[index]
|
||||
val ktParameter = DescriptorToSourceUtils.getSourceFromDescriptor(valueParameterDescriptor) as? KtParameter
|
||||
irValueParameter.defaultValue = ktParameter?.defaultValue?.let { defaultValue ->
|
||||
@@ -376,7 +390,8 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
||||
descriptor: ParameterDescriptor,
|
||||
ktElement: KtPureElement?,
|
||||
irOwnerElement: IrElement,
|
||||
name: Name? = null
|
||||
name: Name? = null,
|
||||
index: Int? = null
|
||||
): IrValueParameter {
|
||||
var origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||
if (ktElement is KtParameter) {
|
||||
@@ -392,7 +407,8 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
||||
origin,
|
||||
descriptor, descriptor.type.toIrType(),
|
||||
(descriptor as? ValueParameterDescriptor)?.varargElementType?.toIrType(),
|
||||
name
|
||||
name,
|
||||
index
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+8
-6
@@ -80,10 +80,11 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St
|
||||
|
||||
return statementGenerator.generateCallReceiver(
|
||||
ktCallableReference,
|
||||
resolvedDescriptor,
|
||||
resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver,
|
||||
resolvedDescriptor, resolvedCall.dispatchReceiver,
|
||||
resolvedCall.extensionReceiver,
|
||||
resolvedCall.contextReceivers,
|
||||
isSafe = false
|
||||
).call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
).call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||
generateCallableReference(
|
||||
ktCallableReference,
|
||||
callableReferenceType,
|
||||
@@ -150,10 +151,11 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St
|
||||
val resolvedCall = callBuilder.original
|
||||
return statementGenerator.generateCallReceiver(
|
||||
ktCallableReference,
|
||||
resolvedCall.resultingDescriptor,
|
||||
resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver,
|
||||
resolvedCall.resultingDescriptor, resolvedCall.dispatchReceiver,
|
||||
resolvedCall.extensionReceiver,
|
||||
resolvedCall.contextReceivers,
|
||||
isSafe = false
|
||||
).call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
).call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||
val irDispatchReceiver = dispatchReceiverValue?.loadIfExists()
|
||||
val irExtensionReceiver = extensionReceiverValue?.loadIfExists()
|
||||
check(irDispatchReceiver == null || irExtensionReceiver == null) {
|
||||
|
||||
@@ -84,11 +84,11 @@ val CallBuilder.explicitReceiverType: KotlinType?
|
||||
fun CallBuilder.setExplicitReceiverValue(explicitReceiverValue: IntermediateValue) {
|
||||
val previousCallReceiver = callReceiver
|
||||
callReceiver = object : CallReceiver {
|
||||
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
|
||||
return previousCallReceiver.call { dispatchReceiverValue, _ ->
|
||||
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression {
|
||||
return previousCallReceiver.call { dispatchReceiverValue, _, contextReceiverValues ->
|
||||
val newDispatchReceiverValue = if (hasExtensionReceiver) dispatchReceiverValue else explicitReceiverValue
|
||||
val newExtensionReceiverValue = if (hasExtensionReceiver) explicitReceiverValue else null
|
||||
withDispatchAndExtensionReceivers(newDispatchReceiverValue, newExtensionReceiverValue)
|
||||
withDispatchAndExtensionAndContextReceivers(newDispatchReceiverValue, newExtensionReceiverValue, contextReceiverValues)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -24,7 +24,7 @@ class DynamicMemberLValue(
|
||||
) : LValue, AssignmentReceiver {
|
||||
|
||||
override fun load(): IrExpression =
|
||||
receiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
receiver.call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||
val dynamicReceiver = getDynamicReceiver(dispatchReceiverValue, extensionReceiverValue)
|
||||
|
||||
IrDynamicMemberExpressionImpl(
|
||||
@@ -36,7 +36,7 @@ class DynamicMemberLValue(
|
||||
}
|
||||
|
||||
override fun store(irExpression: IrExpression): IrExpression =
|
||||
receiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
receiver.call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||
val dynamicReceiver = getDynamicReceiver(dispatchReceiverValue, extensionReceiverValue)
|
||||
|
||||
IrDynamicOperatorExpressionImpl(
|
||||
@@ -55,11 +55,11 @@ class DynamicMemberLValue(
|
||||
}
|
||||
|
||||
override fun assign(withLValue: (LValue) -> IrExpression): IrExpression =
|
||||
receiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
receiver.call { dispatchReceiverValue, extensionReceiverValue, contextReceiverValues ->
|
||||
withLValue(
|
||||
DynamicMemberLValue(
|
||||
context, startOffset, endOffset, type, memberName,
|
||||
SimpleCallReceiver(dispatchReceiverValue, extensionReceiverValue)
|
||||
SimpleCallReceiver(dispatchReceiverValue, extensionReceiverValue, contextReceiverValues)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
+2
-2
@@ -24,7 +24,7 @@ class ExtensionInvokeCallReceiver(
|
||||
private val extensionInvokeReceiver: IntermediateValue
|
||||
) : CallReceiver {
|
||||
|
||||
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
|
||||
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression {
|
||||
// extensionInvokeReceiver is actually a first argument:
|
||||
// receiver.extFun(p1, ..., pN)
|
||||
// =>
|
||||
@@ -34,6 +34,6 @@ class ExtensionInvokeCallReceiver(
|
||||
"Extension 'invoke' call should have null as its 1st value argument, got: ${callBuilder.irValueArgumentsByIndex[0]}"
|
||||
}
|
||||
callBuilder.irValueArgumentsByIndex[0] = extensionInvokeReceiver.load()
|
||||
return withDispatchAndExtensionReceivers(functionReceiver, null)
|
||||
return withDispatchAndExtensionAndContextReceivers(functionReceiver, null, emptyList())
|
||||
}
|
||||
}
|
||||
@@ -27,8 +27,8 @@ fun IrVariable.loadAt(startOffset: Int, endOffset: Int): IrExpression =
|
||||
|
||||
fun CallReceiver.adjustForCallee(callee: CallableMemberDescriptor): CallReceiver =
|
||||
object : CallReceiver {
|
||||
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression =
|
||||
this@adjustForCallee.call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression =
|
||||
this@adjustForCallee.call { dispatchReceiverValue, extensionReceiverValue, contextReceiverValues ->
|
||||
val numReceiversPresent = listOfNotNull(dispatchReceiverValue, extensionReceiverValue).size
|
||||
val numReceiversExpected = listOfNotNull(callee.dispatchReceiverParameter, callee.extensionReceiverParameter).size
|
||||
if (numReceiversPresent != numReceiversExpected)
|
||||
@@ -46,7 +46,8 @@ fun CallReceiver.adjustForCallee(callee: CallableMemberDescriptor): CallReceiver
|
||||
dispatchReceiverValue != null && callee.dispatchReceiverParameter == null -> dispatchReceiverValue
|
||||
else -> extensionReceiverValue
|
||||
}
|
||||
withDispatchAndExtensionReceivers(newDispatchReceiverValue, newExtensionReceiverValue)
|
||||
// TODO: Create new context receiver values
|
||||
withDispatchAndExtensionAndContextReceivers(newDispatchReceiverValue, newExtensionReceiverValue, contextReceiverValues)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-7
@@ -40,7 +40,7 @@ abstract class PropertyLValueBase(
|
||||
val superQualifier: IrClassSymbol?
|
||||
) : LValue, AssignmentReceiver {
|
||||
override fun assign(withLValue: (LValue) -> IrExpression) =
|
||||
callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
callReceiver.call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||
val dispatchReceiverVariable2 = dispatchReceiverValue?.let {
|
||||
scope.createTemporaryVariable(dispatchReceiverValue.load(), "this")
|
||||
}
|
||||
@@ -81,7 +81,8 @@ class FieldPropertyLValue(
|
||||
PropertyLValueBase(context, scope, startOffset, endOffset, origin, type, callReceiver, superQualifier) {
|
||||
|
||||
override fun load(): IrExpression =
|
||||
callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
// TODO: Use context receiver values
|
||||
callReceiver.call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||
assert(extensionReceiverValue == null) { "Field can't have an extension receiver: ${field.descriptor}" }
|
||||
IrGetFieldImpl(
|
||||
startOffset, endOffset,
|
||||
@@ -94,7 +95,8 @@ class FieldPropertyLValue(
|
||||
}
|
||||
|
||||
override fun store(irExpression: IrExpression) =
|
||||
callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
// TODO: Use context receiver values
|
||||
callReceiver.call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||
assert(extensionReceiverValue == null) { "Field can't have an extension receiver: ${field.descriptor}" }
|
||||
IrSetFieldImpl(
|
||||
startOffset, endOffset,
|
||||
@@ -114,7 +116,7 @@ class FieldPropertyLValue(
|
||||
field,
|
||||
descriptor,
|
||||
type,
|
||||
SimpleCallReceiver(dispatchReceiver, extensionReceiver),
|
||||
SimpleCallReceiver(dispatchReceiver, extensionReceiver, emptyList()),
|
||||
superQualifier
|
||||
)
|
||||
}
|
||||
@@ -144,7 +146,8 @@ class AccessorPropertyLValue(
|
||||
}
|
||||
|
||||
override fun load(): IrExpression =
|
||||
callReceiver.adjustForCallee(getterDescriptor!!).call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
// TODO: Use context receiver values
|
||||
callReceiver.adjustForCallee(getterDescriptor!!).call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||
IrCallImpl(
|
||||
startOffset, endOffset,
|
||||
type,
|
||||
@@ -161,7 +164,8 @@ class AccessorPropertyLValue(
|
||||
}
|
||||
|
||||
override fun store(irExpression: IrExpression) =
|
||||
callReceiver.adjustForCallee(setterDescriptor!!).call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
// TODO: Use context receiver values
|
||||
callReceiver.adjustForCallee(setterDescriptor!!).call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||
IrCallImpl(
|
||||
startOffset, endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
@@ -184,7 +188,7 @@ class AccessorPropertyLValue(
|
||||
startOffset, endOffset, origin,
|
||||
type, getter, getterDescriptor, setter, setterDescriptor,
|
||||
typeArguments,
|
||||
SimpleCallReceiver(dispatchReceiver, extensionReceiver),
|
||||
SimpleCallReceiver(dispatchReceiver, extensionReceiver, emptyList()),
|
||||
superQualifier
|
||||
)
|
||||
}
|
||||
+6
-3
@@ -31,11 +31,13 @@ class SafeCallReceiver(
|
||||
val startOffset: Int,
|
||||
val endOffset: Int,
|
||||
val extensionReceiver: IntermediateValue?,
|
||||
// TODO: Use context receivers
|
||||
val contextReceivers: List<IntermediateValue>,
|
||||
val dispatchReceiver: IntermediateValue?,
|
||||
val isStatement: Boolean
|
||||
) : CallReceiver {
|
||||
|
||||
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
|
||||
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression {
|
||||
val irTmp = generator.scope.createTemporaryVariable(extensionReceiver?.load() ?: dispatchReceiver!!.load(), "safe_receiver")
|
||||
val safeReceiverValue = VariableLValue(generator.context, irTmp)
|
||||
|
||||
@@ -49,7 +51,7 @@ class SafeCallReceiver(
|
||||
extensionReceiverValue = null
|
||||
}
|
||||
|
||||
val irResult = withDispatchAndExtensionReceivers(dispatchReceiverValue, extensionReceiverValue)
|
||||
val irResult = withDispatchAndExtensionAndContextReceivers(dispatchReceiverValue, extensionReceiverValue, emptyList())
|
||||
|
||||
val resultType = if (isStatement) generator.context.irBuiltIns.unitType else irResult.type.makeNullable()
|
||||
|
||||
@@ -77,8 +79,9 @@ fun IrExpression.safeCallOnDispatchReceiver(
|
||||
SafeCallReceiver(
|
||||
generator, startOffset, endOffset,
|
||||
extensionReceiver = null,
|
||||
contextReceivers = emptyList(),
|
||||
dispatchReceiver = OnceExpressionValue(this),
|
||||
isStatement = false
|
||||
).call { dispatchReceiverValue, _ ->
|
||||
).call { dispatchReceiverValue, _, _ ->
|
||||
ifNotNull(dispatchReceiverValue!!.load())
|
||||
}
|
||||
+2
-2
@@ -33,7 +33,7 @@ class SafeExtensionInvokeCallReceiver(
|
||||
val extensionInvokeReceiver: IntermediateValue
|
||||
) : CallReceiver {
|
||||
|
||||
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
|
||||
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression {
|
||||
// extensionInvokeReceiver is actually a first argument:
|
||||
// receiver?.extFun(p1, ..., pN)
|
||||
// =>
|
||||
@@ -49,7 +49,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 = withDispatchAndExtensionReceivers(functionReceiver, null)
|
||||
val irResult = withDispatchAndExtensionAndContextReceivers(functionReceiver, null, emptyList())
|
||||
|
||||
val resultType = irResult.type.makeNullable()
|
||||
|
||||
|
||||
+4
-3
@@ -20,10 +20,11 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
|
||||
class SimpleCallReceiver(
|
||||
private val dispatchReceiverValue: IntermediateValue?,
|
||||
private val extensionReceiverValue: IntermediateValue?
|
||||
private val extensionReceiverValue: IntermediateValue?,
|
||||
private val contextReceiverValues: List<IntermediateValue>
|
||||
) : CallReceiver {
|
||||
|
||||
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
|
||||
return withDispatchAndExtensionReceivers(dispatchReceiverValue, extensionReceiverValue)
|
||||
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression {
|
||||
return withDispatchAndExtensionAndContextReceivers(dispatchReceiverValue, extensionReceiverValue, contextReceiverValues)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,5 +36,5 @@ interface AssignmentReceiver {
|
||||
}
|
||||
|
||||
interface CallReceiver {
|
||||
fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression
|
||||
fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ class IrCallImpl(
|
||||
type: IrType,
|
||||
symbol: IrSimpleFunctionSymbol,
|
||||
typeArgumentsCount: Int = symbol.descriptor.typeParametersCount,
|
||||
valueArgumentsCount: Int = symbol.descriptor.valueParameters.size,
|
||||
valueArgumentsCount: Int = symbol.descriptor.valueParameters.size + symbol.descriptor.contextReceiverParameters.size,
|
||||
origin: IrStatementOrigin? = null,
|
||||
superQualifierSymbol: IrClassSymbol? = null,
|
||||
) =
|
||||
|
||||
@@ -933,11 +933,12 @@ open class SymbolTable(
|
||||
type: IrType,
|
||||
varargElementType: IrType? = null,
|
||||
name: Name? = null,
|
||||
index: Int? = null,
|
||||
isAssignable: Boolean = false,
|
||||
valueParameterFactory: (IrValueParameterSymbol) -> IrValueParameter = {
|
||||
irFactory.createValueParameter(
|
||||
startOffset, endOffset, origin, it, name ?: nameProvider.nameForDeclaration(descriptor),
|
||||
descriptor.indexOrMinusOne, type, varargElementType, descriptor.isCrossinline, descriptor.isNoinline,
|
||||
index ?: descriptor.indexOrMinusOne, type, varargElementType, descriptor.isCrossinline, descriptor.isNoinline,
|
||||
isHidden = false, isAssignable = isAssignable
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
class View {
|
||||
val coefficient = 42
|
||||
}
|
||||
|
||||
context(View) val Int.dp get() = coefficient * this
|
||||
|
||||
fun box(): String {
|
||||
with(View()) {
|
||||
if (listOf(1, 2, 10).map { it.dp } == listOf(42, 84, 420)) {
|
||||
return "OK"
|
||||
}
|
||||
return "fail"
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
interface NumberOperations {
|
||||
operator fun Number.plus(other: Number): Number
|
||||
}
|
||||
|
||||
object DoubleOperations : NumberOperations {
|
||||
override operator fun Number.plus(other: Number) = this.toDouble() + other.toDouble()
|
||||
}
|
||||
|
||||
data class Matrix(val rows: Int, val columns: Int, val data: Array<out Number>) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as Matrix
|
||||
|
||||
if (rows != other.rows) return false
|
||||
if (columns != other.columns) return false
|
||||
if (!data.contentEquals(other.data)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = rows
|
||||
result = 31 * result + columns
|
||||
result = 31 * result + data.contentHashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
fun matrixOf(rows: Int, columns: Int, vararg data: Number): Matrix {
|
||||
assert(rows * columns == data.size) { "Wrong dimentions" }
|
||||
return Matrix(rows, columns, data)
|
||||
}
|
||||
|
||||
context(NumberOperations) operator fun Matrix.plus(other: Matrix): Matrix {
|
||||
assert(rows == other.rows && columns == other.columns) { "Matrices should have the same dimentions" }
|
||||
return matrixOf(rows, columns, *data.mapIndexed { i, element -> element + other.data[i] }.toTypedArray())
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val m1 = matrixOf(2, 2, 1, 2, 3, 4)
|
||||
val m2 = matrixOf(2, 2, .4, .3, .2, .1)
|
||||
with(DoubleOperations) {
|
||||
return if (m1 + m2 == matrixOf(2, 2, 1.4, 2.3, 3.2, 4.1)) "OK" else "fail"
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
class A {
|
||||
val o = "O"
|
||||
}
|
||||
class B {
|
||||
val k = "K"
|
||||
}
|
||||
|
||||
context(B) fun A.f(a: Any, b: Any) = o + k
|
||||
|
||||
fun B.g(a: A): String {
|
||||
with (a) {
|
||||
return f(1, "2")
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return B().g(A())
|
||||
}
|
||||
+10
@@ -16029,6 +16029,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
public void testWhenFail() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/extensionFunctions/contextReceivers")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class ContextReceivers {
|
||||
@Test
|
||||
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+28
@@ -16107,6 +16107,34 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
public void testWhenFail() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/extensionFunctions/contextReceivers")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class ContextReceivers {
|
||||
@Test
|
||||
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("dp.kt")
|
||||
public void testDp() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/dp.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("plusMatrix.kt")
|
||||
public void testPlusMatrix() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/plusMatrix.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simpleCall.kt")
|
||||
public void testSimpleCall() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/simpleCall.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+13
@@ -13192,6 +13192,19 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
public void testWhenFail() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/extensionFunctions/contextReceivers")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class ContextReceivers extends AbstractLightAnalysisModeTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/extensionProperties")
|
||||
|
||||
Generated
+13
@@ -14778,6 +14778,19 @@ public class VisualizerBlackBoxTestGenerated extends AbstractVisualizerBlackBoxT
|
||||
public void testWhenFail() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/extensionFunctions/contextReceivers")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class ContextReceivers extends AbstractIrJsCodegenBoxES6Test {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+13
@@ -12443,6 +12443,19 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
public void testWhenFail() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/extensionFunctions/contextReceivers")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class ContextReceivers extends AbstractJsCodegenBoxTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+13
@@ -12485,6 +12485,19 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
public void testWhenFail() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/extensionFunctions/contextReceivers")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class ContextReceivers extends AbstractIrJsCodegenBoxTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+13
@@ -10359,6 +10359,19 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
||||
public void testWhenFail() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/extensionFunctions/contextReceivers")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class ContextReceivers extends AbstractIrCodegenBoxWasmTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/extensionProperties")
|
||||
|
||||
Reference in New Issue
Block a user