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
This commit is contained in:
Dmitry Petrov
2017-11-24 12:48:55 +03:00
parent 7bee2ceac7
commit 70d3e6592d
9 changed files with 199 additions and 12 deletions
@@ -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()) {
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -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");
@@ -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");
@@ -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");
@@ -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");