From 79e7ee91e4d98fe18226bee8ee9b339a958e48ea Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 7 Apr 2014 22:29:00 +0400 Subject: [PATCH] Generate bridges for trait implementations properly The intent was to keep the bridge codegen model as simple as possible: we should be able to figure out all necessary bridges only by a minimal interface that FunctionHandle provides (isAbstract, isDeclaration, getOverridden) Add different tests for bridges #KT-318 Obsolete --- compiler/backend-common/src/bridges/impl.kt | 79 +++++++++++++++++-- .../jet/codegen/ClassBodyCodegen.java | 3 +- .../jet/codegen/FunctionCodegen.java | 4 + .../codegen/ImplementationBodyCodegen.java | 78 ++---------------- .../codegen/box/bridges/complexTraitImpl.kt | 28 +++++++ ...verrideInTraitWithRequiredFromTraitImpl.kt | 17 ++++ ...fakeOverrideOfPropertySetterInTraitImpl.kt | 23 ++++++ .../fakeOverrideWithImplementationInTrait.kt | 18 +++++ .../testData/codegen/box/bridges/kt318.kt | 23 ++++++ .../noBridgeOnMutableCollectionInheritance.kt | 22 ++++++ .../box/bridges/traitImplInheritsTraitImpl.kt | 15 ++++ .../traitWithRequiredCovariantOverride.kt | 15 ++++ .../BlackBoxCodegenTestGenerated.java | 40 ++++++++++ .../jet/lang/resolve/OverridingUtil.java | 3 +- 14 files changed, 289 insertions(+), 79 deletions(-) create mode 100644 compiler/testData/codegen/box/bridges/complexTraitImpl.kt create mode 100644 compiler/testData/codegen/box/bridges/fakeOverrideInTraitWithRequiredFromTraitImpl.kt create mode 100644 compiler/testData/codegen/box/bridges/fakeOverrideOfPropertySetterInTraitImpl.kt create mode 100644 compiler/testData/codegen/box/bridges/fakeOverrideWithImplementationInTrait.kt create mode 100644 compiler/testData/codegen/box/bridges/kt318.kt create mode 100644 compiler/testData/codegen/box/bridges/noBridgeOnMutableCollectionInheritance.kt create mode 100644 compiler/testData/codegen/box/bridges/traitImplInheritsTraitImpl.kt create mode 100644 compiler/testData/codegen/box/bridges/traitWithRequiredCovariantOverride.kt diff --git a/compiler/backend-common/src/bridges/impl.kt b/compiler/backend-common/src/bridges/impl.kt index d3ee805f462..71a51f3ab54 100644 --- a/compiler/backend-common/src/bridges/impl.kt +++ b/compiler/backend-common/src/bridges/impl.kt @@ -16,8 +16,12 @@ package org.jetbrains.jet.codegen.bridges -import org.jetbrains.jet.lang.descriptors.FunctionDescriptor -import org.jetbrains.jet.lang.descriptors.Modality +import org.jetbrains.jet.lang.descriptors.* +import org.jetbrains.jet.lang.resolve.DescriptorUtils +import org.jetbrains.jet.lang.resolve.OverridingUtil +import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil +import org.jetbrains.jet.lang.types.TypeUtils +import java.util.LinkedHashSet public fun generateBridgesForFunctionDescriptor( descriptor: FunctionDescriptor, @@ -26,11 +30,72 @@ public fun generateBridgesForFunctionDescriptor( return generateBridges(DescriptorBasedFunctionHandle(descriptor), { signature(it.descriptor) }) } +/** + * An implementation of FunctionHandle based on descriptors. + * + * This implementation workarounds a minor inconvenience in descriptor hierarchy regarding traits with implementations. + * Consider the following hierarchy: + * + * trait A { fun foo() = 42 } + * class B : A + * + * In terms of descriptors, we'll have a declaration in trait A with modality=OPEN and a fake override in class B with modality=OPEN. + * For the purposes of bridge generation though, it's much easier to "move" all implementations out of traits into their child classes, + * i.e. treat the function in A as a declaration with modality=ABSTRACT and a function in B as a _declaration_ with modality=OPEN. + * + * This provides us with the nice invariant that all implementations (concrete declarations) are always in classes. This means we _always_ + * can generate a bridge near an implementation (of course, in case it has a super-declaration with a different signature). Ultimately this + * eases the process of determining what bridges are already generated in our supertypes and need to be inherited, not regenerated. + */ private data class DescriptorBasedFunctionHandle(val descriptor: FunctionDescriptor) : FunctionHandle { - override val isDeclaration: Boolean = descriptor.getKind().isReal() - override val isAbstract: Boolean = descriptor.getModality() == Modality.ABSTRACT + private val _overridden = descriptor.getOverriddenDescriptors().map { DescriptorBasedFunctionHandle(it.getOriginal()) } - override fun getOverridden(): Iterable { - return descriptor.getOverriddenDescriptors().map { DescriptorBasedFunctionHandle(it.getOriginal()) } - } + override val isDeclaration: Boolean = + descriptor.getKind().isReal() || + findTraitImplementation(descriptor) != null + + override val isAbstract: Boolean = + descriptor.getModality() == Modality.ABSTRACT || + DescriptorUtils.isTrait(descriptor.getContainingDeclaration()) + + override fun getOverridden() = _overridden +} + + +/** + * 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 + */ +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 = OverridingUtil.getOverriddenDeclarations(descriptor) + val filteredOverriddenDeclarations = OverridingUtil.filterOutOverridden(LinkedHashSet(overriddenDeclarations)) + + var implementation: CallableMemberDescriptor? = null + for (overriddenDeclaration in filteredOverriddenDeclarations) { + if (DescriptorUtils.isTrait(overriddenDeclaration.getContainingDeclaration()) && overriddenDeclaration.getModality() != Modality.ABSTRACT) { + assert(implementation == null) { "Ambiguous overridden declaration: $descriptor" } + implementation = overriddenDeclaration + } + } + if (implementation == null) { + 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!!.getExpectedThisObject()!!.getType() + for (supertype in containingClass.getDefaultType().getConstructor().getSupertypes()) { + if (!DescriptorUtils.isTrait(supertype.getConstructor().getDeclarationDescriptor()!!) && + TypeUtils.getAllSupertypes(supertype).contains(implClassType)) { + return null + } + } + + return implementation } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index 57822dac2fe..1894b0c0385 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -18,6 +18,7 @@ package org.jetbrains.jet.codegen; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.bridges.BridgesPackage; import org.jetbrains.jet.codegen.context.ClassContext; import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.lang.descriptors.*; @@ -103,7 +104,7 @@ public abstract class ClassBodyCodegen extends MemberCodegen { for (DeclarationDescriptor memberDescriptor : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) { if (memberDescriptor instanceof FunctionDescriptor) { FunctionDescriptor member = (FunctionDescriptor) memberDescriptor; - if (member.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { + if (!member.getKind().isReal() && BridgesPackage.findTraitImplementation(member) == null) { functionCodegen.generateBridges(member); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 33e3a019158..94487331fb9 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -41,6 +41,7 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.JetNamedFunction; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil; import org.jetbrains.jet.lang.resolve.constants.ArrayValue; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.JavaClassValue; @@ -425,6 +426,9 @@ public class FunctionCodegen extends ParentCodegenAwareImpl { if (owner.getContextKind() == OwnerKind.TRAIT_IMPL) return; if (isTrait(descriptor.getContainingDeclaration())) return; + // If the function doesn't have a physical declaration among super-functions, it's a SAM adapter or alike and doesn't need bridges + if (CallResolverUtil.isOrOverridesSynthesized(descriptor)) return; + Set> bridgesToGenerate = BridgesPackage.generateBridgesForFunctionDescriptor( descriptor, new Function1() { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index bc3b0e1112b..4e3a2e47415 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -17,15 +17,14 @@ package org.jetbrains.jet.codegen; import com.google.common.collect.Lists; -import com.google.common.collect.Sets; import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.util.Pair; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.codegen.binding.CalculatedClosure; import org.jetbrains.jet.codegen.binding.CodegenBinding; import org.jetbrains.jet.codegen.binding.MutableClosure; +import org.jetbrains.jet.codegen.bridges.BridgesPackage; import org.jetbrains.jet.codegen.context.ClassContext; import org.jetbrains.jet.codegen.context.ConstructorContext; import org.jetbrains.jet.codegen.context.MethodContext; @@ -1464,11 +1463,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { private void generateTraitMethods() { if (JetPsiUtil.isTrait(myClass)) return; - for (Pair pair : getTraitImplementations(descriptor)) { - CallableMemberDescriptor inheritedMember = pair.first; - CallableMemberDescriptor traitMember = pair.second; + for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) { + if (!(declaration instanceof CallableMemberDescriptor)) continue; - assert traitMember.getModality() != Modality.ABSTRACT : "Cannot delegate to abstract trait method: " + pair; + CallableMemberDescriptor inheritedMember = (CallableMemberDescriptor) declaration; + CallableMemberDescriptor traitMember = BridgesPackage.findTraitImplementation(inheritedMember); + if (traitMember == null) continue; + + assert traitMember.getModality() != Modality.ABSTRACT : "Cannot delegate to abstract trait method: " + inheritedMember; // inheritedMember can be abstract here. In order for FunctionCodegen to generate the method body, we're creating a copy here // with traitMember's modality @@ -1810,70 +1812,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } - - /** - * Return pairs of descriptors. First is member of this that should be implemented by delegating to trait, - * second is member of trait that contain implementation. - */ - @NotNull - private static List> getTraitImplementations(@NotNull ClassDescriptor classDescriptor) { - List> result = Lists.newArrayList(); - - for (DeclarationDescriptor declaration : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) { - if (!(declaration instanceof CallableMemberDescriptor)) continue; - - CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration; - - CallableMemberDescriptor implementation = findTraitImplementation(callableMemberDescriptor); - if (implementation != null) { - result.add(Pair.create(callableMemberDescriptor, implementation)); - } - } - - return result; - } - - /** - * Given a fake override descriptor, returns an overridden non-abstract descriptor whose container is a trait - */ - @Nullable - private static CallableMemberDescriptor findTraitImplementation(@NotNull CallableMemberDescriptor descriptor) { - if (descriptor.getKind().isReal()) return null; - - if (CallResolverUtil.isOrOverridesSynthesized(descriptor)) return null; - - Collection overriddenDeclarations = OverridingUtil.getOverriddenDeclarations(descriptor); - - Collection filteredOverriddenDeclarations = - OverridingUtil.filterOutOverridden(Sets.newLinkedHashSet(overriddenDeclarations)); - - int count = 0; - CallableMemberDescriptor implementation = null; - - for (CallableMemberDescriptor overriddenDeclaration : filteredOverriddenDeclarations) { - if (isTrait(overriddenDeclaration.getContainingDeclaration()) && overriddenDeclaration.getModality() != Modality.ABSTRACT) { - implementation = overriddenDeclaration; - count++; - } - } - if (implementation == null) { - return null; - } - - assert count == 1 : "Ambiguous overridden declaration: " + descriptor; - - ClassDescriptor containingClass = (ClassDescriptor) descriptor.getContainingDeclaration(); - for (JetType supertype : containingClass.getDefaultType().getConstructor().getSupertypes()) { - //noinspection ConstantConditions - if (!isTrait(supertype.getConstructor().getDeclarationDescriptor()) && - TypeUtils.getAllSupertypes(supertype).contains(implementation.getExpectedThisObject().getType())) { - return null; - } - } - - return implementation; - } - public void addClassObjectPropertyToCopy(PropertyDescriptor descriptor, Object defaultValue) { if (classObjectPropertiesToCopy == null) { classObjectPropertiesToCopy = new ArrayList(); diff --git a/compiler/testData/codegen/box/bridges/complexTraitImpl.kt b/compiler/testData/codegen/box/bridges/complexTraitImpl.kt new file mode 100644 index 00000000000..18f692013e5 --- /dev/null +++ b/compiler/testData/codegen/box/bridges/complexTraitImpl.kt @@ -0,0 +1,28 @@ +import java.util.ArrayList +import java.util.Arrays + +abstract class A { + abstract fun foo(): List +} + +trait B { + fun foo(): ArrayList = ArrayList(Arrays.asList("B")) +} + +open class C : A(), B + +trait D { + fun foo(): Collection +} + +class E : D, C() + +fun box(): String { + val e = E() + var r = e.foo()[0] + r += (e : D).foo().iterator().next() + r += (e : C).foo()[0] + r += (e : B).foo()[0] + r += (e : A).foo()[0] + return if (r == "BBBBB") "OK" else "Fail: $r" +} diff --git a/compiler/testData/codegen/box/bridges/fakeOverrideInTraitWithRequiredFromTraitImpl.kt b/compiler/testData/codegen/box/bridges/fakeOverrideInTraitWithRequiredFromTraitImpl.kt new file mode 100644 index 00000000000..ba0b79cbdda --- /dev/null +++ b/compiler/testData/codegen/box/bridges/fakeOverrideInTraitWithRequiredFromTraitImpl.kt @@ -0,0 +1,17 @@ +abstract class A { + abstract fun foo(): Any +} + +trait B { + fun foo(): String = "B" +} + +trait C : A, B + +class D : A(), C + +fun box(): String { + val d = D() + val r = d.foo() + (d : C).foo() + (d : B).foo() + (d : A).foo() + return if (r == "BBBB") "OK" else "Fail: $r" +} diff --git a/compiler/testData/codegen/box/bridges/fakeOverrideOfPropertySetterInTraitImpl.kt b/compiler/testData/codegen/box/bridges/fakeOverrideOfPropertySetterInTraitImpl.kt new file mode 100644 index 00000000000..4a6a4a9e2fa --- /dev/null +++ b/compiler/testData/codegen/box/bridges/fakeOverrideOfPropertySetterInTraitImpl.kt @@ -0,0 +1,23 @@ +var result = "" + +trait A { + var foo: String + get() = result + set(value) { + result += value + } +} + +abstract class B { + abstract var foo: Any +} + +class C : A, B() + +fun box(): String { + val c = C() + c.foo = "1" + (c : B).foo = "2" + (c : A).foo = "3" + return if (result == "123") "OK" else "Fail: $result" +} diff --git a/compiler/testData/codegen/box/bridges/fakeOverrideWithImplementationInTrait.kt b/compiler/testData/codegen/box/bridges/fakeOverrideWithImplementationInTrait.kt new file mode 100644 index 00000000000..3f3a0750cf1 --- /dev/null +++ b/compiler/testData/codegen/box/bridges/fakeOverrideWithImplementationInTrait.kt @@ -0,0 +1,18 @@ +trait A { + fun foo(): String = "A" +} + +trait B { + fun foo(): Any +} + +class C : A, B + +fun box(): String { + val c = C() + var result = "" + result += c.foo() + result += (c : B).foo() + result += (c : A).foo() + return if (result == "AAA") "OK" else "Fail: $result" +} diff --git a/compiler/testData/codegen/box/bridges/kt318.kt b/compiler/testData/codegen/box/bridges/kt318.kt new file mode 100644 index 00000000000..c1929b1d81a --- /dev/null +++ b/compiler/testData/codegen/box/bridges/kt318.kt @@ -0,0 +1,23 @@ +var result = "" + +trait Base +open class Child : Base + +trait A { + fun foo(a : E) { + result += "A" + } +} + +class B : A { + override fun foo(a : E) { + result += "B" + } +} + +fun box(): String { + val b = B() + b.foo(Child()) + (b : A).foo(Child()) + return if (result == "BB") "OK" else "Fail: $result" +} diff --git a/compiler/testData/codegen/box/bridges/noBridgeOnMutableCollectionInheritance.kt b/compiler/testData/codegen/box/bridges/noBridgeOnMutableCollectionInheritance.kt new file mode 100644 index 00000000000..46ea079d779 --- /dev/null +++ b/compiler/testData/codegen/box/bridges/noBridgeOnMutableCollectionInheritance.kt @@ -0,0 +1,22 @@ +import java.util.ArrayList +import java.util.Arrays + +trait A { + fun foo(): Collection +} + +trait B : A { + override fun foo(): MutableCollection +} + +class C : B { + override fun foo(): MutableList = ArrayList(Arrays.asList("C")) +} + +fun box(): String { + val c = C() + var r = c.foo().iterator().next() + r += (c : B).foo().iterator().next() + r += (c : A).foo().iterator().next() + return if (r == "CCC") "OK" else "Fail: $r" +} diff --git a/compiler/testData/codegen/box/bridges/traitImplInheritsTraitImpl.kt b/compiler/testData/codegen/box/bridges/traitImplInheritsTraitImpl.kt new file mode 100644 index 00000000000..1e5a588a0ab --- /dev/null +++ b/compiler/testData/codegen/box/bridges/traitImplInheritsTraitImpl.kt @@ -0,0 +1,15 @@ +trait A { + fun foo(): Any = "A" +} + +trait B : A { + override fun foo(): String = "B" +} + +class C : B + +fun box(): String { + val c = C() + var r = c.foo() + (c : B).foo() + (c : A).foo() + return if (r == "BBB") "OK" else "Fail: $r" +} diff --git a/compiler/testData/codegen/box/bridges/traitWithRequiredCovariantOverride.kt b/compiler/testData/codegen/box/bridges/traitWithRequiredCovariantOverride.kt new file mode 100644 index 00000000000..35e0c38a30c --- /dev/null +++ b/compiler/testData/codegen/box/bridges/traitWithRequiredCovariantOverride.kt @@ -0,0 +1,15 @@ +open class A { + open fun foo(): Any = "A" +} + +trait B : A { + override fun foo(): String = "B" +} + +class C : A(), B + +fun box(): String { + val c = C() + val r = c.foo() + (c : B).foo() + (c : A).foo() + return if (r == "BBB") "OK" else "Fail: $r" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index cbba360a843..4b201ef249b 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -290,6 +290,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/bridges/complexMultiInheritance.kt"); } + @TestMetadata("complexTraitImpl.kt") + public void testComplexTraitImpl() throws Exception { + doTest("compiler/testData/codegen/box/bridges/complexTraitImpl.kt"); + } + @TestMetadata("delegation.kt") public void testDelegation() throws Exception { doTest("compiler/testData/codegen/box/bridges/delegation.kt"); @@ -315,11 +320,26 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/bridges/fakeGenericCovariantOverride.kt"); } + @TestMetadata("fakeOverrideInTraitWithRequiredFromTraitImpl.kt") + public void testFakeOverrideInTraitWithRequiredFromTraitImpl() throws Exception { + doTest("compiler/testData/codegen/box/bridges/fakeOverrideInTraitWithRequiredFromTraitImpl.kt"); + } + + @TestMetadata("fakeOverrideOfPropertySetterInTraitImpl.kt") + public void testFakeOverrideOfPropertySetterInTraitImpl() throws Exception { + doTest("compiler/testData/codegen/box/bridges/fakeOverrideOfPropertySetterInTraitImpl.kt"); + } + @TestMetadata("fakeOverrideOfTraitImpl.kt") public void testFakeOverrideOfTraitImpl() throws Exception { doTest("compiler/testData/codegen/box/bridges/fakeOverrideOfTraitImpl.kt"); } + @TestMetadata("fakeOverrideWithImplementationInTrait.kt") + public void testFakeOverrideWithImplementationInTrait() throws Exception { + doTest("compiler/testData/codegen/box/bridges/fakeOverrideWithImplementationInTrait.kt"); + } + @TestMetadata("fakeOverrideWithSeveralSuperDeclarations.kt") public void testFakeOverrideWithSeveralSuperDeclarations() throws Exception { doTest("compiler/testData/codegen/box/bridges/fakeOverrideWithSeveralSuperDeclarations.kt"); @@ -360,6 +380,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/bridges/kt2920.kt"); } + @TestMetadata("kt318.kt") + public void testKt318() throws Exception { + doTest("compiler/testData/codegen/box/bridges/kt318.kt"); + } + @TestMetadata("longChainOneBridge.kt") public void testLongChainOneBridge() throws Exception { doTest("compiler/testData/codegen/box/bridges/longChainOneBridge.kt"); @@ -375,6 +400,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/bridges/methodFromTrait.kt"); } + @TestMetadata("noBridgeOnMutableCollectionInheritance.kt") + public void testNoBridgeOnMutableCollectionInheritance() throws Exception { + doTest("compiler/testData/codegen/box/bridges/noBridgeOnMutableCollectionInheritance.kt"); + } + @TestMetadata("overrideAbstractProperty.kt") public void testOverrideAbstractProperty() throws Exception { doTest("compiler/testData/codegen/box/bridges/overrideAbstractProperty.kt"); @@ -440,6 +470,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/bridges/simpleUpperBound.kt"); } + @TestMetadata("traitImplInheritsTraitImpl.kt") + public void testTraitImplInheritsTraitImpl() throws Exception { + doTest("compiler/testData/codegen/box/bridges/traitImplInheritsTraitImpl.kt"); + } + + @TestMetadata("traitWithRequiredCovariantOverride.kt") + public void testTraitWithRequiredCovariantOverride() throws Exception { + doTest("compiler/testData/codegen/box/bridges/traitWithRequiredCovariantOverride.kt"); + } + @TestMetadata("twoParentsWithDifferentMethodsTwoBridges.kt") public void testTwoParentsWithDifferentMethodsTwoBridges() throws Exception { doTest("compiler/testData/codegen/box/bridges/twoParentsWithDifferentMethodsTwoBridges.kt"); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java index 793728e0e65..65a5b44654b 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java @@ -318,7 +318,8 @@ public class OverridingUtil { * * @see CallableMemberDescriptor.Kind#isReal() */ - public static Collection getOverriddenDeclarations(CallableMemberDescriptor descriptor) { + @NotNull + public static Collection getOverriddenDeclarations(@NotNull CallableMemberDescriptor descriptor) { Map result = Maps.newHashMap(); getOverriddenDeclarations(descriptor, result); return result.values();