From 70d3e6592d47419810049194b0c835501c3480c6 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Fri, 24 Nov 2017 12:48:55 +0300 Subject: [PATCH] Unwrap object member imported by name before determining receivers Existing code for receiver generation accidentally worked in most cases for object members imported by name. However, it generated strange bytecode (such as GETFIELD AnObject.INSTANCE GETFIELD AnObject.INSTANCE POP ), and worked incorrectly for augmented assignments. #KT-21343 Fixed Target versions 1.2.20 --- .../jetbrains/kotlin/codegen/StackValue.java | 29 +++++++++++-------- ...ssToExtensionPropertyImportedFromObject.kt | 24 +++++++++++++++ ...ArrayAccessToPropertyImportedFromObject.kt | 20 +++++++++++++ ...ntToExtensionPropertyImportedFromObject.kt | 24 +++++++++++++++ ...dAssignmentToPropertyImportedFromObject.kt | 18 ++++++++++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 24 +++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 24 +++++++++++++++ .../LightAnalysisModeTestGenerated.java | 24 +++++++++++++++ .../semantics/JsCodegenBoxTestGenerated.java | 24 +++++++++++++++ 9 files changed, 199 insertions(+), 12 deletions(-) create mode 100644 compiler/testData/codegen/box/objects/compoundAssignmentToArrayAccessToExtensionPropertyImportedFromObject.kt create mode 100644 compiler/testData/codegen/box/objects/compoundAssignmentToArrayAccessToPropertyImportedFromObject.kt create mode 100644 compiler/testData/codegen/box/objects/compoundAssignmentToExtensionPropertyImportedFromObject.kt create mode 100644 compiler/testData/codegen/box/objects/compoundAssignmentToPropertyImportedFromObject.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java index 11193c5aaf4..de1ee92fcbb 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java @@ -529,8 +529,15 @@ public abstract class StackValue { } ReceiverValue callExtensionReceiver = resolvedCall.getExtensionReceiver(); + + boolean isImportedObjectMember = false; + if (descriptor instanceof ImportedFromObjectCallableDescriptor) { + isImportedObjectMember = true; + descriptor = ((ImportedFromObjectCallableDescriptor) descriptor).getCallableFromObject(); + } + if (callDispatchReceiver != null || callExtensionReceiver != null - || isLocalFunCall(callableMethod) || isCallToMemberObjectImportedByName(resolvedCall)) { + || isLocalFunCall(callableMethod) || isImportedObjectMember) { ReceiverParameterDescriptor dispatchReceiverParameter = descriptor.getDispatchReceiverParameter(); ReceiverParameterDescriptor extensionReceiverParameter = descriptor.getExtensionReceiverParameter(); @@ -540,10 +547,10 @@ public abstract class StackValue { boolean hasExtensionReceiver = callExtensionReceiver != null; StackValue dispatchReceiver = platformStaticCallIfPresent( - genReceiver(hasExtensionReceiver ? none() : receiver, codegen, resolvedCall, callableMethod, callDispatchReceiver, false), + genReceiver(hasExtensionReceiver ? none() : receiver, codegen, descriptor, callableMethod, callDispatchReceiver, false), descriptor ); - StackValue extensionReceiver = genReceiver(receiver, codegen, resolvedCall, callableMethod, callExtensionReceiver, true); + StackValue extensionReceiver = genReceiver(receiver, codegen, descriptor, callableMethod, callExtensionReceiver, true); return CallReceiver.generateCallReceiver( resolvedCall, codegen, callableMethod, dispatchReceiverParameter, dispatchReceiver, @@ -556,22 +563,24 @@ public abstract class StackValue { private static StackValue genReceiver( @NotNull StackValue receiver, @NotNull ExpressionCodegen codegen, - @NotNull ResolvedCall resolvedCall, + @NotNull CallableDescriptor descriptor, @Nullable Callable callableMethod, @Nullable ReceiverValue receiverValue, boolean isExtension ) { + DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); if (receiver == none()) { if (receiverValue != null) { return codegen.generateReceiverValue(receiverValue, false); } else if (isLocalFunCall(callableMethod) && !isExtension) { - StackValue value = codegen.findLocalOrCapturedValue(resolvedCall.getResultingDescriptor().getOriginal()); - assert value != null : "Local fun should be found in locals or in captured params: " + resolvedCall; + StackValue value = codegen.findLocalOrCapturedValue(descriptor.getOriginal()); + assert value != null : "Local fun should be found in locals or in captured params: " + descriptor; return value; } - else if (isCallToMemberObjectImportedByName(resolvedCall)) { - return singleton(((ImportedFromObjectCallableDescriptor) resolvedCall.getResultingDescriptor()).getContainingObject(), codegen.typeMapper); + else if (!isExtension && DescriptorUtils.isObject(containingDeclaration)) { + // Object member could be imported by name, in which case it has no explicit dispatch receiver + return singleton((ClassDescriptor) containingDeclaration, codegen.typeMapper); } } else if (receiverValue != null) { @@ -580,10 +589,6 @@ public abstract class StackValue { return none(); } - private static boolean isCallToMemberObjectImportedByName(@NotNull ResolvedCall resolvedCall) { - return resolvedCall.getResultingDescriptor() instanceof ImportedFromObjectCallableDescriptor; - } - private static StackValue platformStaticCallIfPresent(@NotNull StackValue resultReceiver, @NotNull CallableDescriptor descriptor) { if (CodegenUtilKt.isJvmStaticInObjectOrClass(descriptor)) { if (resultReceiver.canHaveSideEffects()) { diff --git a/compiler/testData/codegen/box/objects/compoundAssignmentToArrayAccessToExtensionPropertyImportedFromObject.kt b/compiler/testData/codegen/box/objects/compoundAssignmentToArrayAccessToExtensionPropertyImportedFromObject.kt new file mode 100644 index 00000000000..358a1b9ddfd --- /dev/null +++ b/compiler/testData/codegen/box/objects/compoundAssignmentToArrayAccessToExtensionPropertyImportedFromObject.kt @@ -0,0 +1,24 @@ +// WITH_RUNTIME + +import Host.x + +object A { + var xx = intArrayOf(0) +} + +object Host { + val A.x get() = A.xx +} + +fun box(): String { + A.x[0] += 1 + if (A.x[0] != 1) return "Fail 1: ${A.x[0]}" + + A.x[0]++ + if (A.x[0] != 2) return "Fail 2: ${A.x[0]}" + + ++A.x[0] + if (A.x[0] != 3) return "Fail 3: ${A.x[0]}" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/objects/compoundAssignmentToArrayAccessToPropertyImportedFromObject.kt b/compiler/testData/codegen/box/objects/compoundAssignmentToArrayAccessToPropertyImportedFromObject.kt new file mode 100644 index 00000000000..bfe33afdeaa --- /dev/null +++ b/compiler/testData/codegen/box/objects/compoundAssignmentToArrayAccessToPropertyImportedFromObject.kt @@ -0,0 +1,20 @@ +// WITH_RUNTIME + +import Host.x + +object Host { + val x = intArrayOf(0) +} + +fun box(): String { + x[0] += 1 + if (x[0] != 1) return "Fail 1: ${x[0]}" + + x[0]++ + if (x[0] != 2) return "Fail 2: ${x[0]}" + + ++x[0] + if (x[0] != 3) return "Fail 3: ${x[0]}" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/objects/compoundAssignmentToExtensionPropertyImportedFromObject.kt b/compiler/testData/codegen/box/objects/compoundAssignmentToExtensionPropertyImportedFromObject.kt new file mode 100644 index 00000000000..593c7d6242f --- /dev/null +++ b/compiler/testData/codegen/box/objects/compoundAssignmentToExtensionPropertyImportedFromObject.kt @@ -0,0 +1,24 @@ +import Host.x + +object A { + var xx = 0 +} + +object Host { + var A.x + get() = A.xx + set(v) { A.xx = v } +} + +fun box(): String { + A.x += 1 + if (A.x != 1) return "Fail 1: ${A.x}" + + A.x++ + if (A.x != 2) return "Fail 2: ${A.x}" + + ++A.x + if (A.x != 3) return "Fail 3: ${A.x}" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/objects/compoundAssignmentToPropertyImportedFromObject.kt b/compiler/testData/codegen/box/objects/compoundAssignmentToPropertyImportedFromObject.kt new file mode 100644 index 00000000000..db7d276732c --- /dev/null +++ b/compiler/testData/codegen/box/objects/compoundAssignmentToPropertyImportedFromObject.kt @@ -0,0 +1,18 @@ +import Host.x + +object Host { + var x = 0 +} + +fun box(): String { + x += 1 + if (x != 1) return "Fail 1: $x" + + x++ + if (x != 2) return "Fail 2: $x" + + ++x + if (x != 3) return "Fail 3: $x" + + return "OK" +} \ No newline at end of file diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 17e7815e58d..b12933c8744 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -12452,6 +12452,30 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("compoundAssignmentToArrayAccessToExtensionPropertyImportedFromObject.kt") + public void testCompoundAssignmentToArrayAccessToExtensionPropertyImportedFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToArrayAccessToExtensionPropertyImportedFromObject.kt"); + doTest(fileName); + } + + @TestMetadata("compoundAssignmentToArrayAccessToPropertyImportedFromObject.kt") + public void testCompoundAssignmentToArrayAccessToPropertyImportedFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToArrayAccessToPropertyImportedFromObject.kt"); + doTest(fileName); + } + + @TestMetadata("compoundAssignmentToExtensionPropertyImportedFromObject.kt") + public void testCompoundAssignmentToExtensionPropertyImportedFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToExtensionPropertyImportedFromObject.kt"); + doTest(fileName); + } + + @TestMetadata("compoundAssignmentToPropertyImportedFromObject.kt") + public void testCompoundAssignmentToPropertyImportedFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToPropertyImportedFromObject.kt"); + doTest(fileName); + } + @TestMetadata("flist.kt") public void testFlist() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/flist.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 1db20d31e53..6a46a529d30 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -12452,6 +12452,30 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("compoundAssignmentToArrayAccessToExtensionPropertyImportedFromObject.kt") + public void testCompoundAssignmentToArrayAccessToExtensionPropertyImportedFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToArrayAccessToExtensionPropertyImportedFromObject.kt"); + doTest(fileName); + } + + @TestMetadata("compoundAssignmentToArrayAccessToPropertyImportedFromObject.kt") + public void testCompoundAssignmentToArrayAccessToPropertyImportedFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToArrayAccessToPropertyImportedFromObject.kt"); + doTest(fileName); + } + + @TestMetadata("compoundAssignmentToExtensionPropertyImportedFromObject.kt") + public void testCompoundAssignmentToExtensionPropertyImportedFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToExtensionPropertyImportedFromObject.kt"); + doTest(fileName); + } + + @TestMetadata("compoundAssignmentToPropertyImportedFromObject.kt") + public void testCompoundAssignmentToPropertyImportedFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToPropertyImportedFromObject.kt"); + doTest(fileName); + } + @TestMetadata("flist.kt") public void testFlist() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/flist.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index a7d1e64913a..a2902489207 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -12452,6 +12452,30 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes doTest(fileName); } + @TestMetadata("compoundAssignmentToArrayAccessToExtensionPropertyImportedFromObject.kt") + public void testCompoundAssignmentToArrayAccessToExtensionPropertyImportedFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToArrayAccessToExtensionPropertyImportedFromObject.kt"); + doTest(fileName); + } + + @TestMetadata("compoundAssignmentToArrayAccessToPropertyImportedFromObject.kt") + public void testCompoundAssignmentToArrayAccessToPropertyImportedFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToArrayAccessToPropertyImportedFromObject.kt"); + doTest(fileName); + } + + @TestMetadata("compoundAssignmentToExtensionPropertyImportedFromObject.kt") + public void testCompoundAssignmentToExtensionPropertyImportedFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToExtensionPropertyImportedFromObject.kt"); + doTest(fileName); + } + + @TestMetadata("compoundAssignmentToPropertyImportedFromObject.kt") + public void testCompoundAssignmentToPropertyImportedFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToPropertyImportedFromObject.kt"); + doTest(fileName); + } + @TestMetadata("flist.kt") public void testFlist() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/flist.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 5958ea4e180..6b2b64f0890 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -13514,6 +13514,30 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("compoundAssignmentToArrayAccessToExtensionPropertyImportedFromObject.kt") + public void testCompoundAssignmentToArrayAccessToExtensionPropertyImportedFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToArrayAccessToExtensionPropertyImportedFromObject.kt"); + doTest(fileName); + } + + @TestMetadata("compoundAssignmentToArrayAccessToPropertyImportedFromObject.kt") + public void testCompoundAssignmentToArrayAccessToPropertyImportedFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToArrayAccessToPropertyImportedFromObject.kt"); + doTest(fileName); + } + + @TestMetadata("compoundAssignmentToExtensionPropertyImportedFromObject.kt") + public void testCompoundAssignmentToExtensionPropertyImportedFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToExtensionPropertyImportedFromObject.kt"); + doTest(fileName); + } + + @TestMetadata("compoundAssignmentToPropertyImportedFromObject.kt") + public void testCompoundAssignmentToPropertyImportedFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToPropertyImportedFromObject.kt"); + doTest(fileName); + } + @TestMetadata("flist.kt") public void testFlist() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/flist.kt");