Use common instance receiver generation logic for 'this' expression

Otherwise it would skip private companion object accessor generation.
This commit is contained in:
Dmitry Petrov
2018-09-25 15:23:55 +03:00
parent c4337f753e
commit 7949ac1080
7 changed files with 75 additions and 23 deletions
@@ -2673,28 +2673,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
public StackValue generateReceiverValue(@Nullable ReceiverValue receiverValue, boolean isSuper) {
if (receiverValue instanceof ImplicitClassReceiver) {
ClassDescriptor receiverDescriptor = ((ImplicitClassReceiver) receiverValue).getDeclarationDescriptor();
if (DescriptorUtils.isCompanionObject(receiverDescriptor)) {
CallableMemberDescriptor contextDescriptor = context.getContextDescriptor();
if (contextDescriptor instanceof FunctionDescriptor && receiverDescriptor == contextDescriptor.getContainingDeclaration()) {
return StackValue.LOCAL_0;
}
else if (isPossiblyUninitializedSingleton(receiverDescriptor) && isInsideSingleton(receiverDescriptor)) {
return generateThisOrOuterFromContext(receiverDescriptor, false, false);
}
else if (couldUseDirectAccessToCompanionObject(receiverDescriptor, context)) {
return StackValue.singleton(receiverDescriptor, typeMapper);
}
else {
return generateAccessorCallForCompanionObject(receiverDescriptor);
}
}
else if (receiverDescriptor instanceof ScriptDescriptor) {
return generateScriptReceiver((ScriptDescriptor) receiverDescriptor);
}
else {
return StackValue.thisOrOuter(this, receiverDescriptor, isSuper,
receiverValue instanceof CastImplicitClassReceiver || isEnumEntry(receiverDescriptor));
}
return generateInstanceReceiver(receiverDescriptor, isSuper,
receiverValue instanceof CastImplicitClassReceiver || isEnumEntry(receiverDescriptor));
}
else if (receiverValue instanceof ExtensionReceiver) {
return generateExtensionReceiver(((ExtensionReceiver) receiverValue).getDeclarationDescriptor());
@@ -2714,6 +2694,35 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
}
private StackValue generateInstanceReceiver(
@NotNull ClassDescriptor receiverDescriptor,
boolean isSuper,
boolean castReceiver
) {
if (DescriptorUtils.isCompanionObject(receiverDescriptor)) {
CallableMemberDescriptor contextDescriptor = context.getContextDescriptor();
if (contextDescriptor instanceof FunctionDescriptor && receiverDescriptor == contextDescriptor.getContainingDeclaration()) {
return StackValue.LOCAL_0;
}
else if (isPossiblyUninitializedSingleton(receiverDescriptor) && isInsideSingleton(receiverDescriptor)) {
return generateThisOrOuterFromContext(receiverDescriptor, false, false);
}
else if (couldUseDirectAccessToCompanionObject(receiverDescriptor, context)) {
return StackValue.singleton(receiverDescriptor, typeMapper);
}
else {
return generateAccessorCallForCompanionObject(receiverDescriptor);
}
}
else if (receiverDescriptor instanceof ScriptDescriptor) {
return generateScriptReceiver((ScriptDescriptor) receiverDescriptor);
}
else {
return StackValue.thisOrOuter(this, receiverDescriptor, isSuper, castReceiver);
}
}
@NotNull
private StackValue generateAccessorCallForCompanionObject(@NotNull ClassDescriptor companionObjectDescriptor) {
DeclarationDescriptor hostClassDescriptor = companionObjectDescriptor.getContainingDeclaration();
@@ -4408,8 +4417,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
public StackValue visitThisExpression(@NotNull KtThisExpression expression, StackValue receiver) {
DeclarationDescriptor descriptor = bindingContext.get(REFERENCE_TARGET, expression.getInstanceReference());
if (descriptor instanceof ClassDescriptor) {
return generateInstanceReceiver((ClassDescriptor) descriptor, false, true);
//TODO rewrite with context.lookupInContext()
return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, false, true);
//return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, false, true);
}
if (descriptor instanceof CallableDescriptor) {
return generateExtensionReceiver((CallableDescriptor) descriptor);
@@ -0,0 +1,17 @@
// !LANGUAGE: +ProperVisibilityForCompanionObjectInstanceField
// IGNORE_BACKEND: JS, JS_IR, JVM_IR
inline fun on(body: () -> Any) = body().toString()
class A {
fun test() = foo()
private companion object {
private fun foo() = on { this }
override fun toString() = "OK"
}
}
fun box() = A().test()
@@ -15118,6 +15118,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/objects/companionObjectAccess"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("kt27117.kt")
public void testKt27117() throws Exception {
runTest("compiler/testData/codegen/box/objects/companionObjectAccess/kt27117.kt");
}
@TestMetadata("privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt")
public void testPrivateCompanionObjectAccessedFromAnonymousObjectInNestedClass() throws Exception {
runTest("compiler/testData/codegen/box/objects/companionObjectAccess/privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt");
@@ -15118,6 +15118,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/objects/companionObjectAccess"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("kt27117.kt")
public void testKt27117() throws Exception {
runTest("compiler/testData/codegen/box/objects/companionObjectAccess/kt27117.kt");
}
@TestMetadata("privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt")
public void testPrivateCompanionObjectAccessedFromAnonymousObjectInNestedClass() throws Exception {
runTest("compiler/testData/codegen/box/objects/companionObjectAccess/privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt");
@@ -15123,6 +15123,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/objects/companionObjectAccess"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
}
@TestMetadata("kt27117.kt")
public void testKt27117() throws Exception {
runTest("compiler/testData/codegen/box/objects/companionObjectAccess/kt27117.kt");
}
@TestMetadata("privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt")
public void testPrivateCompanionObjectAccessedFromAnonymousObjectInNestedClass() throws Exception {
runTest("compiler/testData/codegen/box/objects/companionObjectAccess/privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt");
@@ -13303,6 +13303,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/objects/companionObjectAccess"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("kt27117.kt")
public void testKt27117() throws Exception {
runTest("compiler/testData/codegen/box/objects/companionObjectAccess/kt27117.kt");
}
@TestMetadata("privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt")
public void testPrivateCompanionObjectAccessedFromAnonymousObjectInNestedClass() throws Exception {
runTest("compiler/testData/codegen/box/objects/companionObjectAccess/privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt");
@@ -14348,6 +14348,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/objects/companionObjectAccess"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
}
@TestMetadata("kt27117.kt")
public void testKt27117() throws Exception {
runTest("compiler/testData/codegen/box/objects/companionObjectAccess/kt27117.kt");
}
@TestMetadata("privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt")
public void testPrivateCompanionObjectAccessedFromAnonymousObjectInNestedClass() throws Exception {
runTest("compiler/testData/codegen/box/objects/companionObjectAccess/privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt");