Don't generate delegates on overriding jvm8 interfaces
This commit is contained in:
@@ -1326,7 +1326,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) {
|
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) {
|
||||||
FunctionDescriptor traitFun = entry.getKey();
|
FunctionDescriptor traitFun = entry.getKey();
|
||||||
//skip java 8 default methods
|
//skip java 8 default methods
|
||||||
if (!(traitFun instanceof JavaCallableMemberDescriptor)) {
|
if (!(traitFun instanceof JavaCallableMemberDescriptor || isJvm8InterfaceMember(traitFun, state))) {
|
||||||
generateDelegationToTraitImpl(traitFun, entry.getValue());
|
generateDelegationToTraitImpl(traitFun, entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,11 @@ import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
|||||||
import org.jetbrains.kotlin.codegen.context.FacadePartWithSourceFile;
|
import org.jetbrains.kotlin.codegen.context.FacadePartWithSourceFile;
|
||||||
import org.jetbrains.kotlin.codegen.context.MethodContext;
|
import org.jetbrains.kotlin.codegen.context.MethodContext;
|
||||||
import org.jetbrains.kotlin.codegen.context.RootContext;
|
import org.jetbrains.kotlin.codegen.context.RootContext;
|
||||||
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor;
|
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor;
|
||||||
import org.jetbrains.kotlin.load.kotlin.ModuleMapping;
|
import org.jetbrains.kotlin.load.kotlin.*;
|
||||||
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityUtilsKt;
|
|
||||||
import org.jetbrains.kotlin.psi.Call;
|
import org.jetbrains.kotlin.psi.Call;
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
import org.jetbrains.kotlin.psi.KtFunction;
|
import org.jetbrains.kotlin.psi.KtFunction;
|
||||||
@@ -43,7 +43,9 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
|||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
|
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@@ -58,6 +60,32 @@ public class JvmCodegenUtil {
|
|||||||
private JvmCodegenUtil() {
|
private JvmCodegenUtil() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isJvm6Interface(@NotNull DeclarationDescriptor descriptor, @NotNull GenerationState state) {
|
||||||
|
if (!DescriptorUtils.isInterface(descriptor)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (descriptor instanceof DeserializedClassDescriptor) {
|
||||||
|
SourceElement source = ((DeserializedClassDescriptor) descriptor).getSource();
|
||||||
|
if (source instanceof KotlinJvmBinarySourceElement) {
|
||||||
|
KotlinJvmBinaryClass binaryClass = ((KotlinJvmBinarySourceElement) source).getBinaryClass();
|
||||||
|
assert binaryClass instanceof FileBasedKotlinClass :
|
||||||
|
"KotlinJvmBinaryClass should be subclass of FileBasedKotlinClass, but " + binaryClass;
|
||||||
|
return ((FileBasedKotlinClass) binaryClass).getClassVersion() == Opcodes.V1_6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !state.isJvm8Target();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isJvm8Interface(@NotNull DeclarationDescriptor descriptor, @NotNull GenerationState state) {
|
||||||
|
return DescriptorUtils.isInterface(descriptor) && !isJvm6Interface(descriptor, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isJvm8InterfaceMember(@NotNull CallableMemberDescriptor descriptor, @NotNull GenerationState state) {
|
||||||
|
DeclarationDescriptor declaration = descriptor.getContainingDeclaration();
|
||||||
|
return DescriptorUtils.isInterface(declaration) && !isJvm6Interface(declaration, state);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isJvmInterface(DeclarationDescriptor descriptor) {
|
public static boolean isJvmInterface(DeclarationDescriptor descriptor) {
|
||||||
if (descriptor instanceof ClassDescriptor) {
|
if (descriptor instanceof ClassDescriptor) {
|
||||||
ClassKind kind = ((ClassDescriptor) descriptor).getKind();
|
ClassKind kind = ((ClassDescriptor) descriptor).getKind();
|
||||||
|
|||||||
Vendored
+21
@@ -0,0 +1,21 @@
|
|||||||
|
// KOTLIN_CONFIGURATION_FLAGS: +JVM.JVM_8_TARGET
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// FULL_JDK
|
||||||
|
interface Test {
|
||||||
|
fun test() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestClass : Test {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
try {
|
||||||
|
TestClass::class.java.getDeclaredMethod("test")
|
||||||
|
}
|
||||||
|
catch (e: NoSuchMethodException) {
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
return "fail"
|
||||||
|
}
|
||||||
Vendored
+21
@@ -0,0 +1,21 @@
|
|||||||
|
// KOTLIN_CONFIGURATION_FLAGS: +JVM.JVM_8_TARGET
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// FULL_JDK
|
||||||
|
interface Test {
|
||||||
|
fun test() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Test2 : Test {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
try {
|
||||||
|
Test2::class.java.getDeclaredMethod("test")
|
||||||
|
}
|
||||||
|
catch (e: NoSuchMethodException) {
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
return "fail"
|
||||||
|
}
|
||||||
Vendored
+25
@@ -0,0 +1,25 @@
|
|||||||
|
// KOTLIN_CONFIGURATION_FLAGS: +JVM.JVM_8_TARGET
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// FULL_JDK
|
||||||
|
interface Test {
|
||||||
|
fun test() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Test2 : Test {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Test3 : Test2 {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
try {
|
||||||
|
Test3::class.java.getDeclaredMethod("test")
|
||||||
|
}
|
||||||
|
catch (e: NoSuchMethodException) {
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
return "fail"
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// KOTLIN_CONFIGURATION_FLAGS: +JVM.JVM_8_TARGET
|
||||||
|
interface Test {
|
||||||
|
fun test(): String {
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestClass : Test {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return TestClass().test()
|
||||||
|
}
|
||||||
+42
@@ -119,6 +119,48 @@ public class BlackBoxWithJava8CodegenTestGenerated extends AbstractBlackBoxCodeg
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/java8/box/jvm8")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Jvm8 extends AbstractBlackBoxCodegenTest {
|
||||||
|
public void testAllFilesPresentInJvm8() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/java8/box/jvm8"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleCall.kt")
|
||||||
|
public void testSimpleCall() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/jvm8/simpleCall.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/java8/box/jvm8/noDelegation")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class NoDelegation extends AbstractBlackBoxCodegenTest {
|
||||||
|
public void testAllFilesPresentInNoDelegation() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/java8/box/jvm8/noDelegation"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("noDelegationToDefaultMethodInClass.kt")
|
||||||
|
public void testNoDelegationToDefaultMethodInClass() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/jvm8/noDelegation/noDelegationToDefaultMethodInClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("noDelegationToDefaultMethodInInterface.kt")
|
||||||
|
public void testNoDelegationToDefaultMethodInInterface() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/jvm8/noDelegation/noDelegationToDefaultMethodInInterface.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("noDelegationToDefaultMethodInInterface2.kt")
|
||||||
|
public void testNoDelegationToDefaultMethodInInterface2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/jvm8/noDelegation/noDelegationToDefaultMethodInInterface2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/java8/box/mapRemove")
|
@TestMetadata("compiler/testData/codegen/java8/box/mapRemove")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user