diff --git a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/bridges/impl.kt b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/bridges/impl.kt index 88aba59025d..63399e7628a 100644 --- a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/bridges/impl.kt +++ b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/bridges/impl.kt @@ -16,11 +16,12 @@ package org.jetbrains.kotlin.backend.common.bridges -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.OverrideResolver import org.jetbrains.kotlin.resolve.calls.CallResolverUtil -import org.jetbrains.kotlin.types.TypeUtils public fun generateBridgesForFunctionDescriptor( descriptor: FunctionDescriptor, @@ -64,36 +65,50 @@ private data class DescriptorBasedFunctionHandle(val descriptor: FunctionDescrip /** * Given a fake override in a class, returns an overridden declaration with implementation in trait, such that a method delegating to that * trait implementation should be generated into the class containing the fake override; or null if the given function is not a fake - * override of any trait implementation or such method was already generated into some superclass + * override of any trait implementation or such method was already generated into the superclass or is a method from Any. */ public fun findTraitImplementation(descriptor: CallableMemberDescriptor): CallableMemberDescriptor? { if (descriptor.getKind().isReal()) return null if (CallResolverUtil.isOrOverridesSynthesized(descriptor)) return null - // TODO: this logic is quite common for bridge generation, find a way to abstract it to a single place - // TODO: don't use filterOutOverridden() here, it's an internal front-end utility (see its implementation) - val overriddenDeclarations = OverrideResolver.getOverriddenDeclarations(descriptor) - val filteredOverriddenDeclarations = OverrideResolver.filterOutOverridden(overriddenDeclarations) + val implementation = findImplementationFromInterface(descriptor) ?: return null + val immediateConcreteSuper = firstSuperMethodFromKotlin(descriptor, implementation) ?: return null - var implementation: CallableMemberDescriptor? = null - for (overriddenDeclaration in filteredOverriddenDeclarations) { - if (DescriptorUtils.isTrait(overriddenDeclaration.getContainingDeclaration()) && overriddenDeclaration.getModality() != Modality.ABSTRACT) { - implementation = overriddenDeclaration - } - } - if (implementation == null) { + if (!DescriptorUtils.isTrait(immediateConcreteSuper.getContainingDeclaration())) { + // If this implementation is already generated into the superclass, we need not generate it again, it'll be inherited return null } - // If this implementation is already generated into one of the superclasses, we need not generate it again, it'll be inherited - val containingClass = descriptor.getContainingDeclaration() as ClassDescriptor - val implClassType = implementation!!.getDispatchReceiverParameter()!!.getType() - for (supertype in containingClass.getDefaultType().getConstructor().getSupertypes()) { - if (!DescriptorUtils.isTrait(supertype.getConstructor().getDeclarationDescriptor()!!) && - TypeUtils.getAllSupertypes(supertype).contains(implClassType)) { - return null - } - } - - return implementation + return immediateConcreteSuper +} + +/** + * Given a fake override, returns an overridden non-abstract function from an interface which is the actual implementation of this function + * that should be called when the given fake override is called. + */ +public fun findImplementationFromInterface(descriptor: CallableMemberDescriptor): CallableMemberDescriptor? { + val overridden = OverrideResolver.getOverriddenDeclarations(descriptor) + val filtered = OverrideResolver.filterOutOverridden(overridden) + + val result = filtered.firstOrNull { it.getModality() != Modality.ABSTRACT } ?: return null + + val container = result.getContainingDeclaration() + if (DescriptorUtils.isClass(container) || DescriptorUtils.isEnumClass(container)) return null + + return result +} + +/** + * Given a fake override and its implementation (non-abstract declaration) somewhere in supertypes, + * returns the first immediate super function of the given fake override which overrides that implementation. + * The returned function should be called from TImpl-bridges generated for the given fake override. + */ +public fun firstSuperMethodFromKotlin( + descriptor: CallableMemberDescriptor, + implementation: CallableMemberDescriptor +): CallableMemberDescriptor? { + return descriptor.getOverriddenDescriptors().firstOrNull { overridden -> + overridden.getModality() != Modality.ABSTRACT && + (overridden == implementation || OverrideResolver.overrides(overridden, implementation)) + } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/TraitImplBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/TraitImplBodyCodegen.java index 48bd6ac8610..9e9ed47279a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/TraitImplBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/TraitImplBodyCodegen.java @@ -21,15 +21,27 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.context.ClassContext; import org.jetbrains.kotlin.codegen.state.GenerationState; +import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor; import org.jetbrains.kotlin.psi.JetClassOrObject; import org.jetbrains.kotlin.resolve.DescriptorUtils; +import org.jetbrains.kotlin.resolve.jvm.diagnostics.DiagnosticsPackage; +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature; +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature; +import org.jetbrains.org.objectweb.asm.Type; +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; +import java.util.Iterator; +import java.util.List; + +import static org.jetbrains.kotlin.backend.common.bridges.BridgesPackage.findImplementationFromInterface; +import static org.jetbrains.kotlin.backend.common.bridges.BridgesPackage.firstSuperMethodFromKotlin; import static org.jetbrains.kotlin.codegen.AsmUtil.writeKotlinSyntheticClassAnnotation; import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass; +import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration; import static org.jetbrains.org.objectweb.asm.Opcodes.*; public class TraitImplBodyCodegen extends ClassBodyCodegen { - public TraitImplBodyCodegen( @NotNull JetClassOrObject aClass, @NotNull ClassContext context, @@ -52,6 +64,91 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen { v.visitSource(myClass.getContainingFile().getName(), null); } + @Override + protected void generateSyntheticParts() { + for (DeclarationDescriptor memberDescriptor : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) { + if (!(memberDescriptor instanceof CallableMemberDescriptor)) continue; + + CallableMemberDescriptor fakeOverride = (CallableMemberDescriptor) memberDescriptor; + if (fakeOverride.getKind().isReal()) continue; + if (fakeOverride.getVisibility() == Visibilities.INVISIBLE_FAKE) continue; + if (fakeOverride.getModality() == Modality.ABSTRACT) continue; + + CallableMemberDescriptor implementation = findImplementationFromInterface(fakeOverride); + if (implementation == null) continue; + + // If implementation is located in a Java interface, it will be inherited via normal Java rules + if (implementation instanceof JavaMethodDescriptor) continue; + + // We create a copy of the function with kind = DECLARATION so that FunctionCodegen will generate its body + CallableMemberDescriptor copy = fakeOverride.copy( + fakeOverride.getContainingDeclaration(), Modality.OPEN, fakeOverride.getVisibility(), + CallableMemberDescriptor.Kind.DECLARATION, true + ); + + if (fakeOverride instanceof FunctionDescriptor) { + generateDelegationToSuperTraitImpl((FunctionDescriptor) copy, (FunctionDescriptor) implementation); + } + else if (fakeOverride instanceof PropertyDescriptor) { + PropertyGetterDescriptor getter = ((PropertyDescriptor) copy).getGetter(); + PropertyGetterDescriptor implGetter = ((PropertyDescriptor) implementation).getGetter(); + if (getter != null && implGetter != null) { + generateDelegationToSuperTraitImpl(getter, implGetter); + } + PropertySetterDescriptor setter = ((PropertyDescriptor) copy).getSetter(); + PropertySetterDescriptor implSetter = ((PropertyDescriptor) implementation).getSetter(); + if (setter != null && implSetter != null) { + generateDelegationToSuperTraitImpl(setter, implSetter); + } + } + } + } + + private void generateDelegationToSuperTraitImpl(@NotNull FunctionDescriptor descriptor, @NotNull FunctionDescriptor implementation) { + final FunctionDescriptor delegateTo = (FunctionDescriptor) firstSuperMethodFromKotlin(descriptor, implementation); + if (delegateTo == null) return; + + // We can't call super methods from Java 1.8 interfaces because that requires INVOKESPECIAL which is forbidden from TImpl class + if (delegateTo instanceof JavaMethodDescriptor) return; + + functionCodegen.generateMethod( + DiagnosticsPackage.DelegationToTraitImpl(descriptorToDeclaration(descriptor), descriptor), + descriptor, + new FunctionGenerationStrategy.CodegenBased(state, descriptor) { + @Override + public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { + InstructionAdapter iv = codegen.v; + + CallableMethod method = typeMapper.mapToCallableMethod(delegateTo, true, context); + List myParameters = signature.getValueParameters(); + List calleeParameters = method.getValueParameters(); + + if (myParameters.size() != calleeParameters.size()) { + throw new AssertionError( + String.format( + "Method from super interface has a different signature.\n" + + "This method:\n%s\n%s\n%s\nSuper method:\n%s\n%s\n%s", + callableDescriptor, signature, myParameters, delegateTo, method, calleeParameters + ) + ); + } + + int k = 0; + Iterator it = calleeParameters.iterator(); + for (JvmMethodParameterSignature parameter : myParameters) { + Type type = parameter.getAsmType(); + StackValue.local(k, type).put(it.next().getAsmType(), iv); + k += type.getSize(); + } + + method.genInvokeInstruction(iv); + StackValue.coerce(method.getReturnType(), signature.getReturnType(), iv); + iv.areturn(signature.getReturnType()); + } + } + ); + } + @Override protected void generateKotlinAnnotation() { writeKotlinSyntheticClassAnnotation(v, DescriptorUtils.isTopLevelOrInnerClass(descriptor) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java index 0ed7d67631a..e865c4163a9 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java @@ -578,7 +578,7 @@ public class JetTypeMapper { } else { invokeOpcode = INVOKESTATIC; - signature = mapSignature(functionDescriptor, OwnerKind.TRAIT_IMPL); + signature = mapSignature(descriptor.getOriginal(), OwnerKind.TRAIT_IMPL); owner = mapTraitImpl(currentOwner); } } diff --git a/compiler/java8-tests/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJava8CodegenTestGenerated.java b/compiler/java8-tests/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJava8CodegenTestGenerated.java index 886acb407b8..7b21cb4d729 100644 --- a/compiler/java8-tests/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJava8CodegenTestGenerated.java +++ b/compiler/java8-tests/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJava8CodegenTestGenerated.java @@ -77,6 +77,12 @@ public class BlackBoxWithJava8CodegenTestGenerated extends AbstractBlackBoxCodeg doTestWithJava(fileName); } + @TestMetadata("longChainOfKotlinExtendsFromJavaWithDefault") + public void testLongChainOfKotlinExtendsFromJavaWithDefault() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/java8/boxWithJava/longChainOfKotlinExtendsFromJavaWithDefault/"); + doTestWithJava(fileName); + } + @TestMetadata("samOnInterfaceWithDefaultMethod") public void testSamOnInterfaceWithDefaultMethod() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/java8/boxWithJava/samOnInterfaceWithDefaultMethod/"); diff --git a/compiler/testData/codegen/box/traits/kt5393.kt b/compiler/testData/codegen/box/traits/kt5393.kt new file mode 100644 index 00000000000..2b221df2cb3 --- /dev/null +++ b/compiler/testData/codegen/box/traits/kt5393.kt @@ -0,0 +1,17 @@ +interface A { + fun foo(): String { + return "OK" + } +} + +interface B : A + +class C : B { + override fun foo(): String { + return super.foo() + } +} + +fun box(): String { + return C().foo() +} diff --git a/compiler/testData/codegen/box/traits/kt5393_property.kt b/compiler/testData/codegen/box/traits/kt5393_property.kt new file mode 100644 index 00000000000..881fb3ba8ca --- /dev/null +++ b/compiler/testData/codegen/box/traits/kt5393_property.kt @@ -0,0 +1,20 @@ +var result = "Fail" + +interface A { + var foo: String + get() = result + set(value) { result = value } +} + +interface B : A + +class C : B { + override var foo: String + get() = super.foo + set(value) { super.foo = value } +} + +fun box(): String { + C().foo = "OK" + return C().foo +} diff --git a/compiler/testData/codegen/box/traits/kt5393_toString.kt b/compiler/testData/codegen/box/traits/kt5393_toString.kt new file mode 100644 index 00000000000..42bf45ced97 --- /dev/null +++ b/compiler/testData/codegen/box/traits/kt5393_toString.kt @@ -0,0 +1,15 @@ +interface A { + override fun toString(): String { + return "OK" + } +} + +interface B : A + +class C : B { + override fun toString(): String { + return super.toString() + } +} + +fun box() = "${C()}" diff --git a/compiler/testData/codegen/box/traits/traitImplDelegationWithCovariantOverride.kt b/compiler/testData/codegen/box/traits/traitImplDelegationWithCovariantOverride.kt new file mode 100644 index 00000000000..2c8af75f5c0 --- /dev/null +++ b/compiler/testData/codegen/box/traits/traitImplDelegationWithCovariantOverride.kt @@ -0,0 +1,18 @@ +interface A { + fun foo(): Number { + return 42 + } +} + +interface B : A + +class C : B { + override fun foo(): Int { + return super.foo() as Int + } +} + +fun box(): String { + val x = C().foo() + return if (x == 42) "OK" else "Fail: $x" +} diff --git a/compiler/testData/codegen/box/traits/traitImplDiamond.kt b/compiler/testData/codegen/box/traits/traitImplDiamond.kt new file mode 100644 index 00000000000..4d11997cb2a --- /dev/null +++ b/compiler/testData/codegen/box/traits/traitImplDiamond.kt @@ -0,0 +1,15 @@ +interface A { + fun foo() = "Fail" +} + +interface B : A + +interface C : A { + override fun foo() = "OK" +} + +interface D : B, C + +class Impl : D + +fun box(): String = Impl().foo() diff --git a/compiler/testData/codegen/box/traits/traitImplGenericDelegation.kt b/compiler/testData/codegen/box/traits/traitImplGenericDelegation.kt new file mode 100644 index 00000000000..20d8120a12c --- /dev/null +++ b/compiler/testData/codegen/box/traits/traitImplGenericDelegation.kt @@ -0,0 +1,18 @@ +interface A { + fun foo(t: T, u: U): V? { + return null + } +} + +interface B : A + +class C : B { + override fun foo(t: String, u: Int): Runnable? { + return super.foo(t, u) + } +} + +fun box(): String { + val x = C().foo("", 0) + return if (x == null) "OK" else "Fail: $x" +} diff --git a/compiler/testData/codegen/boxAgainstJava/interfaces/inheritJavaInterface.java b/compiler/testData/codegen/boxAgainstJava/interfaces/inheritJavaInterface.java new file mode 100644 index 00000000000..0e732047214 --- /dev/null +++ b/compiler/testData/codegen/boxAgainstJava/interfaces/inheritJavaInterface.java @@ -0,0 +1,3 @@ +interface A { + void foo(); +} diff --git a/compiler/testData/codegen/boxAgainstJava/interfaces/inheritJavaInterface.kt b/compiler/testData/codegen/boxAgainstJava/interfaces/inheritJavaInterface.kt new file mode 100644 index 00000000000..8761a03c611 --- /dev/null +++ b/compiler/testData/codegen/boxAgainstJava/interfaces/inheritJavaInterface.kt @@ -0,0 +1,16 @@ +interface B : A { + fun bar() = 1 +} + +interface C : B + +class D : C { + override fun foo() {} +} + +fun box(): String { + val d = D() + d.foo() + d.bar() + return "OK" +} diff --git a/compiler/testData/codegen/bytecodeText/interfaces/firstInheritedMethodIsAbstract.kt b/compiler/testData/codegen/bytecodeText/interfaces/firstInheritedMethodIsAbstract.kt new file mode 100644 index 00000000000..6cb718150cb --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/interfaces/firstInheritedMethodIsAbstract.kt @@ -0,0 +1,13 @@ +interface A { + fun foo(): String +} + +interface B { + fun foo(): String = "OK" +} + +interface C : A, B + +// There's no 'foo' in A$$TImpl, proguard and other tools may fail if we generate calls to it +// 0 INVOKESTATIC A\$\$TImpl.foo +// 1 INVOKESTATIC B\$\$TImpl.foo diff --git a/compiler/testData/codegen/bytecodeText/interfaces/noAnyMethodsOnInterfaceInheritance.kt b/compiler/testData/codegen/bytecodeText/interfaces/noAnyMethodsOnInterfaceInheritance.kt new file mode 100644 index 00000000000..40fbc9e5754 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/interfaces/noAnyMethodsOnInterfaceInheritance.kt @@ -0,0 +1,15 @@ +// If we generate equals/hashCode/toString in all interfaces, there will be too much bytecode + +interface A { + fun foo(): Number = 42 +} + +interface B : A + +class C : B { + override fun foo(): Int = super.foo() as Int +} + +// 0 equals +// 0 hashCode +// 0 toString diff --git a/compiler/testData/codegen/bytecodeText/traitImplGeneratedOnce.kt b/compiler/testData/codegen/bytecodeText/interfaces/traitImplGeneratedOnce.kt similarity index 100% rename from compiler/testData/codegen/bytecodeText/traitImplGeneratedOnce.kt rename to compiler/testData/codegen/bytecodeText/interfaces/traitImplGeneratedOnce.kt diff --git a/compiler/testData/codegen/java8/boxWithJava/longChainOfKotlinExtendsFromJavaWithDefault/Base.java b/compiler/testData/codegen/java8/boxWithJava/longChainOfKotlinExtendsFromJavaWithDefault/Base.java new file mode 100644 index 00000000000..c628acd5cda --- /dev/null +++ b/compiler/testData/codegen/java8/boxWithJava/longChainOfKotlinExtendsFromJavaWithDefault/Base.java @@ -0,0 +1,5 @@ +public interface Base { + default String foo() { + return "OK"; + } +} diff --git a/compiler/testData/codegen/java8/boxWithJava/longChainOfKotlinExtendsFromJavaWithDefault/derived.kt b/compiler/testData/codegen/java8/boxWithJava/longChainOfKotlinExtendsFromJavaWithDefault/derived.kt new file mode 100644 index 00000000000..d692890341c --- /dev/null +++ b/compiler/testData/codegen/java8/boxWithJava/longChainOfKotlinExtendsFromJavaWithDefault/derived.kt @@ -0,0 +1,11 @@ +interface K1 : Base + +interface K2 : K1 + +interface K3 : K2 + +class C : K3 { + override fun foo() = super.foo() +} + +fun box(): String = C().foo() diff --git a/compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitFunctionOverriddenByPropertyInTrait.kt b/compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitFunctionOverriddenByPropertyInTrait.kt deleted file mode 100644 index 0500cd621d7..00000000000 --- a/compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitFunctionOverriddenByPropertyInTrait.kt +++ /dev/null @@ -1,8 +0,0 @@ -interface T { - fun getX() = 1 -} - -interface C : T { - val x: Int - get() = 1 -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitPropertyOverriddenByFunctionInTrait.kt b/compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitPropertyOverriddenByFunctionInTrait.kt deleted file mode 100644 index 106aa378526..00000000000 --- a/compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitPropertyOverriddenByFunctionInTrait.kt +++ /dev/null @@ -1,8 +0,0 @@ -interface T { - val x: Int - get() = 1 -} - -interface C : T { - fun getX() = 1 -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitFunctionOverriddenByPropertyInTrait.kt b/compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitFunctionOverriddenByPropertyInTrait.kt new file mode 100644 index 00000000000..ad59f3be327 --- /dev/null +++ b/compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitFunctionOverriddenByPropertyInTrait.kt @@ -0,0 +1,8 @@ +interface T { + fun getX() = 1 +} + +interface C : T { + val x: Int + get() = 1 +} diff --git a/compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitFunctionOverriddenByPropertyInTrait.txt b/compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitFunctionOverriddenByPropertyInTrait.txt similarity index 100% rename from compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitFunctionOverriddenByPropertyInTrait.txt rename to compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitFunctionOverriddenByPropertyInTrait.txt diff --git a/compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitPropertyOverriddenByFunctionInTrait.kt b/compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitPropertyOverriddenByFunctionInTrait.kt new file mode 100644 index 00000000000..f2e4efdac56 --- /dev/null +++ b/compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitPropertyOverriddenByFunctionInTrait.kt @@ -0,0 +1,8 @@ +interface T { + val x: Int + get() = 1 +} + +interface C : T { + fun getX() = 1 +} diff --git a/compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitPropertyOverriddenByFunctionInTrait.txt b/compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitPropertyOverriddenByFunctionInTrait.txt similarity index 100% rename from compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitPropertyOverriddenByFunctionInTrait.txt rename to compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitPropertyOverriddenByFunctionInTrait.txt diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index de4ce2d3559..84293d09ec6 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -4328,12 +4328,6 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } - @TestMetadata("traitFunctionOverriddenByPropertyInTrait.kt") - public void testTraitFunctionOverriddenByPropertyInTrait() throws Exception { - String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitFunctionOverriddenByPropertyInTrait.kt"); - doTest(fileName); - } - @TestMetadata("traitFunctionOverriddenByPropertyNoImpl.kt") public void testTraitFunctionOverriddenByPropertyNoImpl() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitFunctionOverriddenByPropertyNoImpl.kt"); @@ -4346,12 +4340,6 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } - @TestMetadata("traitPropertyOverriddenByFunctionInTrait.kt") - public void testTraitPropertyOverriddenByFunctionInTrait() throws Exception { - String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitPropertyOverriddenByFunctionInTrait.kt"); - doTest(fileName); - } - @TestMetadata("traitPropertyOverriddenByFunctionNoImpl.kt") public void testTraitPropertyOverriddenByFunctionNoImpl() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitPropertyOverriddenByFunctionNoImpl.kt"); @@ -4712,6 +4700,18 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("traitFunctionOverriddenByPropertyInTrait.kt") + public void testTraitFunctionOverriddenByPropertyInTrait() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitFunctionOverriddenByPropertyInTrait.kt"); + doTest(fileName); + } + + @TestMetadata("traitPropertyOverriddenByFunctionInTrait.kt") + public void testTraitPropertyOverriddenByFunctionInTrait() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitPropertyOverriddenByFunctionInTrait.kt"); + doTest(fileName); + } + @TestMetadata("twoTraits.kt") public void testTwoTraits() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/twoTraits.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 770a07fb593..a9168eb9b64 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -215,12 +215,6 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { doTest(fileName); } - @TestMetadata("traitImplGeneratedOnce.kt") - public void testTraitImplGeneratedOnce() throws Exception { - String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/traitImplGeneratedOnce.kt"); - doTest(fileName); - } - @TestMetadata("compiler/testData/codegen/bytecodeText/boxingOptimization") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -512,6 +506,33 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { } } + @TestMetadata("compiler/testData/codegen/bytecodeText/interfaces") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Interfaces extends AbstractBytecodeTextTest { + public void testAllFilesPresentInInterfaces() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/interfaces"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("firstInheritedMethodIsAbstract.kt") + public void testFirstInheritedMethodIsAbstract() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/interfaces/firstInheritedMethodIsAbstract.kt"); + doTest(fileName); + } + + @TestMetadata("noAnyMethodsOnInterfaceInheritance.kt") + public void testNoAnyMethodsOnInterfaceInheritance() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/interfaces/noAnyMethodsOnInterfaceInheritance.kt"); + doTest(fileName); + } + + @TestMetadata("traitImplGeneratedOnce.kt") + public void testTraitImplGeneratedOnce() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/interfaces/traitImplGeneratedOnce.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/codegen/bytecodeText/lazyCodegen") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxAgainstJavaCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxAgainstJavaCodegenTestGenerated.java index a37e80bc007..e1eb33ee306 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxAgainstJavaCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxAgainstJavaCodegenTestGenerated.java @@ -395,6 +395,21 @@ public class BlackBoxAgainstJavaCodegenTestGenerated extends AbstractBlackBoxCod } } + @TestMetadata("compiler/testData/codegen/boxAgainstJava/interfaces") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Interfaces extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInInterfaces() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxAgainstJava/interfaces"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("inheritJavaInterface.kt") + public void testInheritJavaInterface() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/interfaces/inheritJavaInterface.kt"); + doTestAgainstJava(fileName); + } + } + @TestMetadata("compiler/testData/codegen/boxAgainstJava/notNullAssertions") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java index 55623172907..788e123df67 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -7045,6 +7045,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("kt5393.kt") + public void testKt5393() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/kt5393.kt"); + doTest(fileName); + } + + @TestMetadata("kt5393_property.kt") + public void testKt5393_property() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/kt5393_property.kt"); + doTest(fileName); + } + + @TestMetadata("kt5393_toString.kt") + public void testKt5393_toString() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/kt5393_toString.kt"); + doTest(fileName); + } + @TestMetadata("kt5495.kt") public void testKt5495() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/kt5495.kt"); @@ -7057,6 +7075,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("traitImplDelegationWithCovariantOverride.kt") + public void testTraitImplDelegationWithCovariantOverride() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/traitImplDelegationWithCovariantOverride.kt"); + doTest(fileName); + } + + @TestMetadata("traitImplDiamond.kt") + public void testTraitImplDiamond() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/traitImplDiamond.kt"); + doTest(fileName); + } + + @TestMetadata("traitImplGenericDelegation.kt") + public void testTraitImplGenericDelegation() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/traitImplGenericDelegation.kt"); + doTest(fileName); + } + @TestMetadata("traitWithPrivateExtension.kt") public void testTraitWithPrivateExtension() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/traitWithPrivateExtension.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyAccessorDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyAccessorDescriptor.java index 02e4a7ba736..e17863e7e37 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyAccessorDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyAccessorDescriptor.java @@ -18,6 +18,8 @@ package org.jetbrains.kotlin.descriptors; import org.jetbrains.annotations.NotNull; +import java.util.Set; + public interface PropertyAccessorDescriptor extends FunctionDescriptor { boolean hasBody(); @@ -27,6 +29,10 @@ public interface PropertyAccessorDescriptor extends FunctionDescriptor { @Override PropertyAccessorDescriptor getOriginal(); + @Override + @NotNull + Set getOverriddenDescriptors(); + @NotNull PropertyDescriptor getCorrespondingProperty(); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyGetterDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyGetterDescriptor.java index 1905a0e7bfa..1f2f779e57d 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyGetterDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyGetterDescriptor.java @@ -18,8 +18,14 @@ package org.jetbrains.kotlin.descriptors; import org.jetbrains.annotations.NotNull; +import java.util.Set; + public interface PropertyGetterDescriptor extends PropertyAccessorDescriptor { @NotNull @Override PropertyGetterDescriptor getOriginal(); + + @Override + @NotNull + Set getOverriddenDescriptors(); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertySetterDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertySetterDescriptor.java index 62920354434..7fe3a23bd19 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertySetterDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertySetterDescriptor.java @@ -18,8 +18,14 @@ package org.jetbrains.kotlin.descriptors; import org.jetbrains.annotations.NotNull; +import java.util.Set; + public interface PropertySetterDescriptor extends PropertyAccessorDescriptor { @NotNull @Override PropertySetterDescriptor getOriginal(); + + @Override + @NotNull + Set getOverriddenDescriptors(); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyGetterDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyGetterDescriptorImpl.java index f160b44f902..51993df8c88 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyGetterDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyGetterDescriptorImpl.java @@ -56,8 +56,9 @@ public class PropertyGetterDescriptorImpl extends PropertyAccessorDescriptorImpl @NotNull @Override - public Set getOverriddenDescriptors() { - return super.getOverriddenDescriptors(true); + @SuppressWarnings("unchecked") + public Set getOverriddenDescriptors() { + return (Set) super.getOverriddenDescriptors(true); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertySetterDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertySetterDescriptorImpl.java index de7dcf57509..916d26b3028 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertySetterDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertySetterDescriptorImpl.java @@ -72,8 +72,9 @@ public class PropertySetterDescriptorImpl extends PropertyAccessorDescriptorImpl @NotNull @Override - public Set getOverriddenDescriptors() { - return super.getOverriddenDescriptors(false); + @SuppressWarnings("unchecked") + public Set getOverriddenDescriptors() { + return (Set) super.getOverriddenDescriptors(false); } @NotNull