From a760865767db6f4bbae115f06ec544139900bc54 Mon Sep 17 00:00:00 2001 From: Anastasiya Shadrina Date: Thu, 18 Nov 2021 00:53:53 +0700 Subject: [PATCH] [PSI2IR] Generate safe calls correctly --- .../FirBlackBoxCodegenTestGenerated.java | 6 ++++ .../psi2ir/intermediate/SafeCallReceiver.kt | 3 +- .../propertyCompoundAssignment.kt | 33 +++++++++++++++++++ .../IrBlackBoxCodegenTestGenerated.java | 6 ++++ .../impl/PropertyDescriptorImpl.java | 17 +++++++++- .../NativeExtBlackBoxTestGenerated.java | 6 ++++ 6 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/codegen/box/extensionFunctions/contextReceivers/propertyCompoundAssignment.kt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index ceff261f811..19c55892f1d 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -16247,6 +16247,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/plusMatrix.kt"); } + @Test + @TestMetadata("propertyCompoundAssignment.kt") + public void testPropertyCompoundAssignment() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/propertyCompoundAssignment.kt"); + } + @Test @TestMetadata("simpleCall.kt") public void testSimpleCall() throws Exception { 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 12a2ff81515..615ad395c1a 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 @@ -31,7 +31,6 @@ class SafeCallReceiver( val startOffset: Int, val endOffset: Int, val extensionReceiver: IntermediateValue?, - // TODO: Use context receivers val contextReceivers: List, val dispatchReceiver: IntermediateValue?, val isStatement: Boolean @@ -51,7 +50,7 @@ class SafeCallReceiver( extensionReceiverValue = null } - val irResult = withDispatchAndExtensionAndContextReceivers(dispatchReceiverValue, extensionReceiverValue, emptyList()) + val irResult = withDispatchAndExtensionAndContextReceivers(dispatchReceiverValue, extensionReceiverValue, contextReceivers) val resultType = if (isStatement) generator.context.irBuiltIns.unitType else irResult.type.makeNullable() diff --git a/compiler/testData/codegen/box/extensionFunctions/contextReceivers/propertyCompoundAssignment.kt b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/propertyCompoundAssignment.kt new file mode 100644 index 00000000000..8ebfb7be4d2 --- /dev/null +++ b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/propertyCompoundAssignment.kt @@ -0,0 +1,33 @@ +// !LANGUAGE: +ContextReceivers +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND_FIR: JVM_IR + +class LoggingCounter { + var operationCounter = 0 +} + +class A { + context(LoggingCounter) + var p: Int + get(): Int { + operationCounter++ + return 1 + } + set(value: Int) { + operationCounter++ + } +} + +fun foo() = A() + +fun box(): String { + val loggingCounter = LoggingCounter() + with(loggingCounter) { + foo().p += 1 + foo().p = 1 + foo()?.p = 1 + foo().p + } + val operationsTotal = loggingCounter.operationCounter + return if (operationsTotal == 5) "OK" else "$operationsTotal" +} \ No newline at end of file diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 9bd16238325..b3d4b696ef9 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -16247,6 +16247,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/plusMatrix.kt"); } + @Test + @TestMetadata("propertyCompoundAssignment.kt") + public void testPropertyCompoundAssignment() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/propertyCompoundAssignment.kt"); + } + @Test @TestMetadata("simpleCall.kt") public void testSimpleCall() throws Exception { diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyDescriptorImpl.java index 004559c8c1f..70059dcff46 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyDescriptorImpl.java @@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.name.Name; +import org.jetbrains.kotlin.resolve.scopes.receivers.ContextReceiver; import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver; import org.jetbrains.kotlin.types.*; import org.jetbrains.kotlin.utils.SmartSet; @@ -444,7 +445,7 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp List substitutedContextReceivers = new ArrayList(); for (ReceiverParameterDescriptor contextReceiverParameter: contextReceiverParameters) { - ReceiverParameterDescriptor substitutedContextReceiver = substituteParameterDescriptor(substitutor, substitutedDescriptor, + ReceiverParameterDescriptor substitutedContextReceiver = substituteContextParameterDescriptor(substitutor, substitutedDescriptor, contextReceiverParameter); if (substitutedContextReceiver != null) { substitutedContextReceivers.add(substitutedContextReceiver); @@ -541,6 +542,20 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp ); } + private static ReceiverParameterDescriptor substituteContextParameterDescriptor( + TypeSubstitutor substitutor, + PropertyDescriptor substitutedPropertyDescriptor, + ReceiverParameterDescriptor receiverParameterDescriptor + ) { + KotlinType substitutedType = substitutor.substitute(receiverParameterDescriptor.getType(), Variance.IN_VARIANCE); + if (substitutedType == null) return null; + return new ReceiverParameterDescriptorImpl( + substitutedPropertyDescriptor, + new ContextReceiver(substitutedPropertyDescriptor, substitutedType, receiverParameterDescriptor.getValue()), + receiverParameterDescriptor.getAnnotations() + ); + } + private static FunctionDescriptor getSubstitutedInitialSignatureDescriptor( @NotNull TypeSubstitutor substitutor, @NotNull PropertyAccessorDescriptor accessorDescriptor diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeExtBlackBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeExtBlackBoxTestGenerated.java index b834b443590..c6e8724ce48 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeExtBlackBoxTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeExtBlackBoxTestGenerated.java @@ -16434,6 +16434,12 @@ public class NativeExtBlackBoxTestGenerated extends AbstractNativeBlackBoxTest { runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/plusMatrix.kt"); } + @Test + @TestMetadata("propertyCompoundAssignment.kt") + public void testPropertyCompoundAssignment() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/propertyCompoundAssignment.kt"); + } + @Test @TestMetadata("simpleCall.kt") public void testSimpleCall() throws Exception {