From 4dcc373a5afc81ba73fd4d694a3e40fcc165843c Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 25 Jul 2014 17:41:01 +0400 Subject: [PATCH] Fix concrete method inheritance in interfaces For each non-abstract non-declared (i.e. inherited from supertypes) method in an interface we generate its static form to the TImpl, which calls the TImpl method from the corresponding supertype. The accidental override tests changed because we're now trying to generate the delegate for the super method, not knowing that it will clash with the declared method #KT-2888 Fixed #KT-5393 Fixed --- .../kotlin/backend/common/bridges/impl.kt | 65 +++++++----- .../kotlin/codegen/TraitImplBodyCodegen.java | 99 ++++++++++++++++++- .../kotlin/codegen/state/JetTypeMapper.java | 2 +- ...BlackBoxWithJava8CodegenTestGenerated.java | 6 ++ .../testData/codegen/box/traits/kt5393.kt | 17 ++++ .../codegen/box/traits/kt5393_property.kt | 20 ++++ .../codegen/box/traits/kt5393_toString.kt | 15 +++ ...raitImplDelegationWithCovariantOverride.kt | 18 ++++ .../codegen/box/traits/traitImplDiamond.kt | 15 +++ .../box/traits/traitImplGenericDelegation.kt | 18 ++++ .../interfaces/inheritJavaInterface.java | 3 + .../interfaces/inheritJavaInterface.kt | 16 +++ .../firstInheritedMethodIsAbstract.kt | 13 +++ .../noAnyMethodsOnInterfaceInheritance.kt | 15 +++ .../traitImplGeneratedOnce.kt | 0 .../Base.java | 5 + .../derived.kt | 11 +++ ...raitFunctionOverriddenByPropertyInTrait.kt | 8 -- ...raitPropertyOverriddenByFunctionInTrait.kt | 8 -- ...raitFunctionOverriddenByPropertyInTrait.kt | 8 ++ ...aitFunctionOverriddenByPropertyInTrait.txt | 0 ...raitPropertyOverriddenByFunctionInTrait.kt | 8 ++ ...aitPropertyOverriddenByFunctionInTrait.txt | 0 .../checkers/JetDiagnosticsTestGenerated.java | 24 ++--- .../codegen/BytecodeTextTestGenerated.java | 33 +++++-- ...ackBoxAgainstJavaCodegenTestGenerated.java | 15 +++ .../BlackBoxCodegenTestGenerated.java | 36 +++++++ .../PropertyAccessorDescriptor.java | 6 ++ .../descriptors/PropertyGetterDescriptor.java | 6 ++ .../descriptors/PropertySetterDescriptor.java | 6 ++ .../impl/PropertyGetterDescriptorImpl.java | 5 +- .../impl/PropertySetterDescriptorImpl.java | 5 +- 32 files changed, 441 insertions(+), 65 deletions(-) create mode 100644 compiler/testData/codegen/box/traits/kt5393.kt create mode 100644 compiler/testData/codegen/box/traits/kt5393_property.kt create mode 100644 compiler/testData/codegen/box/traits/kt5393_toString.kt create mode 100644 compiler/testData/codegen/box/traits/traitImplDelegationWithCovariantOverride.kt create mode 100644 compiler/testData/codegen/box/traits/traitImplDiamond.kt create mode 100644 compiler/testData/codegen/box/traits/traitImplGenericDelegation.kt create mode 100644 compiler/testData/codegen/boxAgainstJava/interfaces/inheritJavaInterface.java create mode 100644 compiler/testData/codegen/boxAgainstJava/interfaces/inheritJavaInterface.kt create mode 100644 compiler/testData/codegen/bytecodeText/interfaces/firstInheritedMethodIsAbstract.kt create mode 100644 compiler/testData/codegen/bytecodeText/interfaces/noAnyMethodsOnInterfaceInheritance.kt rename compiler/testData/codegen/bytecodeText/{ => interfaces}/traitImplGeneratedOnce.kt (100%) create mode 100644 compiler/testData/codegen/java8/boxWithJava/longChainOfKotlinExtendsFromJavaWithDefault/Base.java create mode 100644 compiler/testData/codegen/java8/boxWithJava/longChainOfKotlinExtendsFromJavaWithDefault/derived.kt delete mode 100644 compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitFunctionOverriddenByPropertyInTrait.kt delete mode 100644 compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitPropertyOverriddenByFunctionInTrait.kt create mode 100644 compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitFunctionOverriddenByPropertyInTrait.kt rename compiler/testData/diagnostics/tests/duplicateJvmSignature/{accidentalOverrides => traitImpl}/traitFunctionOverriddenByPropertyInTrait.txt (100%) create mode 100644 compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitPropertyOverriddenByFunctionInTrait.kt rename compiler/testData/diagnostics/tests/duplicateJvmSignature/{accidentalOverrides => traitImpl}/traitPropertyOverriddenByFunctionInTrait.txt (100%) 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