Support @JvmStatic for interface companion objects in backend

This commit is contained in:
Mikhael Bogdanov
2018-01-23 14:03:51 +01:00
parent 8bfd6d7404
commit cc346aef64
14 changed files with 100 additions and 11 deletions
@@ -45,7 +45,7 @@ public class AccessorForFunctionDescriptor extends AbstractAccessorForFunctionDe
this.nameSuffix = nameSuffix;
initialize(DescriptorUtils.getReceiverParameterType(descriptor.getExtensionReceiverParameter()),
descriptor instanceof ConstructorDescriptor || CodegenUtilKt.isJvmStaticInObjectOrClass(descriptor)
descriptor instanceof ConstructorDescriptor || CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(descriptor)
? null
: descriptor.getDispatchReceiverParameter(),
copyTypeParameters(descriptor),
@@ -47,7 +47,7 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implem
) {
this(property, property.getType(), DescriptorUtils.getReceiverParameterType(property.getExtensionReceiverParameter()),
/* dispatchReceiverParameter = */
CodegenUtilKt.isJvmStaticInObjectOrClass(property) ? null : property.getDispatchReceiverParameter(),
CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(property) ? null : property.getDispatchReceiverParameter(),
containingDeclaration, superCallTarget, nameSuffix,
getterAccessorRequired, setterAccessorRequired);
}
@@ -33,7 +33,6 @@ import org.jetbrains.kotlin.codegen.serialization.JvmStringTable;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.config.JvmTarget;
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.load.java.JavaVisibilities;
@@ -194,7 +193,7 @@ public class AsmUtil {
public static boolean isStaticMethod(OwnerKind kind, CallableMemberDescriptor functionDescriptor) {
return isStaticKind(kind) ||
KotlinTypeMapper.isStaticAccessor(functionDescriptor) ||
CodegenUtilKt.isJvmStaticInObjectOrClass(functionDescriptor);
CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(functionDescriptor);
}
public static boolean isStaticKind(OwnerKind kind) {
@@ -92,7 +92,7 @@ public class CallReceiver extends StackValue {
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
if (CodegenUtilKt.isJvmStaticInObjectOrClass(descriptor)) {
if (CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(descriptor)) {
return Type.VOID_TYPE;
}
@@ -2631,7 +2631,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
if (thisOrOuterClass.equals(context.getThisDescriptor()) &&
!CodegenUtilKt.isJvmStaticInObjectOrClass(context.getFunctionDescriptor())) {
!CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(context.getFunctionDescriptor())) {
return StackValue.local(0, typeMapper.mapType(thisOrOuterClass));
}
else if (shouldGenerateSingletonAsThisOrOuterFromContext(thisOrOuterClass)) {
@@ -822,7 +822,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
((AccessorForCallableDescriptor) accessorDescriptor).getSuperCallTarget() != null
);
boolean isJvmStaticInObjectOrClass = CodegenUtilKt.isJvmStaticInObjectOrClass(functionDescriptor);
boolean isJvmStaticInObjectOrClass = CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(functionDescriptor);
boolean hasDispatchReceiver = !isStaticDeclaration(functionDescriptor) &&
!isNonDefaultInterfaceMember(functionDescriptor, state) &&
!isJvmStaticInObjectOrClass;
@@ -593,7 +593,7 @@ public abstract class StackValue {
}
private static StackValue platformStaticCallIfPresent(@NotNull StackValue resultReceiver, @NotNull CallableDescriptor descriptor) {
if (CodegenUtilKt.isJvmStaticInObjectOrClass(descriptor)) {
if (CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(descriptor)) {
if (resultReceiver.canHaveSideEffects()) {
return coercion(resultReceiver, Type.VOID_TYPE);
}
@@ -253,12 +253,12 @@ fun reportTarget6InheritanceErrorIfNeeded(
}
}
fun CallableDescriptor.isJvmStaticInObjectOrClass(): Boolean =
fun CallableDescriptor.isJvmStaticInObjectOrClassOrInterface(): Boolean =
isJvmStaticIn {
DescriptorUtils.isNonCompanionObject(it) ||
// This is necessary because for generation of @JvmStatic methods from companion of class A
// we create a synthesized descriptor containing in class A
DescriptorUtils.isClassOrEnumClass(it)
DescriptorUtils.isClassOrEnumClass(it) || DescriptorUtils.isInterface(it)
}
fun CallableDescriptor.isJvmStaticInCompanionObject(): Boolean =
@@ -742,7 +742,7 @@ public class KotlinTypeMapper {
boolean isStaticInvocation = (isStaticDeclaration(functionDescriptor) &&
!(functionDescriptor instanceof ImportedFromObjectCallableDescriptor)) ||
isStaticAccessor(functionDescriptor) ||
CodegenUtilKt.isJvmStaticInObjectOrClass(functionDescriptor);
CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(functionDescriptor);
if (isStaticInvocation) {
invokeOpcode = INVOKESTATIC;
isInterfaceMember = currentIsInterface && currentOwner instanceof JavaClassDescriptor;
+27
View File
@@ -0,0 +1,27 @@
// !LANGUAGE: +JvmStaticInInterface
// WITH_RUNTIME
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// FILE: test.kt
fun box(): String {
return Java.test()
}
interface Foo {
companion object {
@JvmStatic
fun foo() = "O"
@JvmStatic
var fooProp = ""
}
}
// FILE: Java.java
public class Java {
public static String test() {
Foo.setFooProp("K");
return Foo.foo() + Foo.getFooProp();
}
}
+27
View File
@@ -0,0 +1,27 @@
// !LANGUAGE: +JvmStaticInInterface
// WITH_RUNTIME
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// FILE: test.kt
fun box(): String {
return Java.test()
}
interface Foo {
companion object {
@JvmStatic
fun foo() = "O"
val fooProp = "K"
@JvmStatic get
}
}
// FILE: Java.java
public class Java {
public static String test() {
return Foo.foo() + Foo.getFooProp();
}
}
@@ -11415,6 +11415,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
@TestMetadata("kt6301.kt")
public void testKt6301() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmStatic/kt6301.kt");
doTest(fileName);
}
@TestMetadata("kt6301_2.kt")
public void testKt6301_2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmStatic/kt6301_2.kt");
doTest(fileName);
}
@TestMetadata("kt9897_static.kt")
public void testKt9897_static() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmStatic/kt9897_static.kt");
@@ -11415,6 +11415,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("kt6301.kt")
public void testKt6301() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmStatic/kt6301.kt");
doTest(fileName);
}
@TestMetadata("kt6301_2.kt")
public void testKt6301_2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmStatic/kt6301_2.kt");
doTest(fileName);
}
@TestMetadata("kt9897_static.kt")
public void testKt9897_static() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmStatic/kt9897_static.kt");
@@ -11415,6 +11415,18 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
doTest(fileName);
}
@TestMetadata("kt6301.kt")
public void testKt6301() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmStatic/kt6301.kt");
doTest(fileName);
}
@TestMetadata("kt6301_2.kt")
public void testKt6301_2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmStatic/kt6301_2.kt");
doTest(fileName);
}
@TestMetadata("kt9897_static.kt")
public void testKt9897_static() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmStatic/kt9897_static.kt");